单点时限: 2.0 sec
内存限制: 256 MB
两个向量a=[a1,a2,⋯,an] 和b=[b1,b2,⋯,bn] 的点积定义为 :
例如,两个三维向量 [1,3,−5] 和 [4,−2,−1] 的点积是
假设允许对每个向量中的坐标值进行重新排列。找出所有排列中点积最小的一种排列,输出最小的那个点积值。
上例中的一种排列 [3,1,−5] 和 [−2,−1,4] 的点积为−27,这是最小的点积。
输入格式
第 1 行:一个整数 T (1⩽T⩽10) 为问题数。
接下来每个问题有 3 行。第 1 行是一个整数 n (1⩽n⩽1000),表示两个向量的维数。第2 行和第 3 行分别表示向量 a 和向量 b。每个向量都有 n 个由一个空格分隔的坐标值 坐标值(−1000⩽坐标值⩽1000) 组成。
输出格式
对于每个问题,输出一行问题的编号(0 开始编号,格式:case #0:
等)。
然后对应每个问题在一行中输出最小点积值。
样例
input
3 3 3 1 -5 -2 -1 4 1 2 -298 5 1 2 3 4 5 1 0 1 0 1
output
case #0: -27 case #1: -596 case #2: 6
解题思路
假设维度是n,让A、B生成全排列然后暴力解的时间复杂度是O()。注意到最小点积可以是 “让vecA中最大的数 × vecB中最小的数” 从而简化运算。
因此本例将vecA递增排序、vecB递减排序,最后求出每个job对应的点积 dotpdt 并输出。
示例代码
#include <iostream>
#include <bits/stdc++.h>
#include <math.h>
using namespace std;
class SingleJob{
public:
int dim;
vector<int> vecA;
vector<int> vecB;
};
int main() {
int jobs, temp;
SingleJob J[10];
// 输入
cin >> jobs;
for(int i=0;i<jobs;i++){
cin >> J[i].dim;
for(int j=0;j<J[i].dim;j++){
cin >> temp;
J[i].vecA.insert(J[i].vecA.end(), temp);
}
for(int j=0;j<J[i].dim;j++){
cin >> temp;
J[i].vecB.insert(J[i].vecB.end(), temp);
}
}
// 输出
int dotpdt=0;
for(int i=0;i<jobs;i++){
sort(J[i].vecA.begin() , J[i].vecA.end());
sort(J[i].vecB.rbegin(), J[i].vecB.rend());
cout << "case #" << i << ":" << endl;
for(int j=0;j<J[i].dim;j++){
dotpdt += J[i].vecA[j] * J[i].vecB[j];
}
cout << sql << endl;
dotpdt = 0;
}
return 0;
}