Code jam Problem A. Minimum Scalar Product

題目描述:

Problem

You are given two vectors v1=(x1,x2,...,xn) and v2=(y1,y2,...,yn). The scalar product of these vectors is a single number, calculated as x1y1+x2y2+...+xnyn.

Suppose you are allowed to permute the coordinates of each vector as you wish. Choose two permutations such that the scalar product of your two new vectors is the smallest possible, and output that minimum scalar product.

Input

The first line of the input file contains integer number T - the number of test cases. For each test case, the first line contains integer number n. The next two lines contain nintegers each, giving the coordinates of v1 and v2 respectively.

Output

For each test case, output a line

Case #X: Y
where X is the test case number, starting from 1, and Y is the minimum scalar product of all permutations of the two given vectors.

Limits

Small dataset

T = 1000
1 ≤ n ≤ 8
-1000 ≤ xiyi ≤ 1000

Large dataset

T = 10
100 ≤ n ≤ 800
-100000 ≤ xiyi ≤ 100000

Sample


Input 
 

Output 
 
2
3
1 3 -5
-2 4 1
5
1 2 3 4 5
1 0 1 0 1

Case #1: -25
Case #2: 6

解題思路:

本題稍微列舉出幾個例子,不難發現規律,將第一個向量的最小和第二個的最大相乘,然後次小與次大,以此類推。這題可以用貪心來理解。

但要證明這個思路的正確性卻不容易,一開始我打算一步一步地來證,即證明去掉最小和最大乘積,將導出比去掉任意其他乘積更小的值,但可惜失敗了。

後來google後發現一個 排序不等式(Rearrangement inequality),wiki上面有對這個定理的詳細證明,於是問題就解決了


#include <cstdio>
#include <algorithm>
using namespace std;

int main(){
    //freopen("A-small-practice.in", "r", stdin);
    freopen("A-large-practice.in", "r", stdin);
    //freopen("A-small-practice.out", "w", stdout);
    freopen("A-large-practice.out", "w", stdout);
    int t;
    scanf("%d", &t);
    for(int kase = 1; kase <= t; kase++){
        int cnt;
        scanf("%d", &cnt);
        int v1[cnt+1], v2[cnt+1];
        for(int i = 0; i < cnt; i++)
            scanf("%d", &v1[i]);
        for(int i = 0; i < cnt; i++)
            scanf("%d", &v2[i]);

        sort(v1, v1+cnt);
        sort(v2, v2+cnt);
        long long res = 0;
        //這裏要注意轉型爲long long,否則還是wrong answer
        for(int i = 0; i < cnt; i++)
            res += (long long)v1[i] * (long long)v2[cnt-1-i];
        printf("Case #%d: %lld\n", kase, res);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章