题目:
ZJM 有四个数列 A,B,C,D,每个数列都有 n 个数字。ZJM 从每个数列中各取出一个数,他想知道有多少种方案使得 4 个数的和为 0。
当一个数列中有多个相同的数字的时候,把它们当做不同的数对待。请你帮帮他吧!
Input:
第一行:n(代表数列中数字的个数) (1≤n≤4000)。
接下来的 n 行中,第 i 行有四个数字,分别表示数列 A,B,C,D 中的第 i 个数字(数字不超过 2 的 28 次方)。
Output:
输出不同组合的个数。
Sample Input:
6
-45 22 42 -16
-41 -27 56 30
-36 53 -37 77
-36 30 -75 -46
26 -38 -10 62
-32 -54 -6 45
Sample Output
5
Hint
样例解释: (-45, -27, 42, 30), (26, 30, -10, -46), (-32, 22, 56, -46),(-32, 30, -75, 77), (-32, -54, 56, 30).
思路:
这道题目考察的是算法优化问题,暴力解显然行不通,怎么解决呢?
我们发现四个数列可以两两组合一下形成两个n*n的数列和为零的问题;
然后对于两个数列,将其中一个排序后我们只需要简单地利用二分的算法去在排序的数列里找未排序数列的对应元素解就可以了。
1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 5 int a[4000][4]; 6 int n,cnt=0; 7 int main(){ 8 cin>>n; 9 int *ab= new int[n*n]; 10 int *cd= new int[n*n]; 11 for(int i=0;i<n;i++){ 12 for(int j=0;j<4;j++){ 13 cin>>a[i][j]; 14 } 15 //sort(a[i],a[i]+n); 16 } 17 int index=0; 18 for(int i=0;i<n;i++){ 19 for(int j=0;j<n;j++){ 20 ab[index]=a[i][0]+a[j][1]; 21 cd[index]=a[i][2]+a[j][3]; 22 index++; 23 } 24 } 25 //sort(ab,ab+n*n); 26 sort(cd,cd+n*n); 27 28 for(int i=0;i<n*n;i++){ 29 int l=0,r=n*n-1; 30 { 31 while(l<=r){ 32 int mid=(l+r)/2; 33 if(ab[i]+cd[mid]>=0){ 34 r=mid-1; 35 index=mid; 36 } 37 else if(ab[i]+cd[mid]<0){ 38 l=mid+1; 39 } 40 } 41 while(index < n*n && ab[i]+cd[index]==0 ) 42 { 43 cnt++; 44 index++; 45 } 46 } 47 } 48 cout<<cnt<<endl; 49 return 0; 50 }