1.链接地址
https://vjudge.net/problem/POJ-2785
2.问题描述
The SUM problem can be formulated as follows: given four lists A, B, C, D of integer values, compute how many quadruplet (a, b, c, d ) ∈ A x B x C x D are such that a + b + c + d = 0 . In the following, we assume that all lists have the same size n .
输入样例
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
输出样例
5
3.解题思路
题目要求从每一列挑出一个数加起来总和为0,直接暴力解会超时,于是有两种优化的方法,分别是
(1)先将第一二列和第三四列分别加起来求出总和,然后将两组总和排序,一组从低开始,一组从高开始互加;
(2)先将第一二列和第三四列分别加起来求出总和,将其中一组排序后,遍历另外一组,通过二分挑选那个排列好的总和数组来相加
下列代码实现第二种算法
4.算法实现源代码
#include<iostream> #include<cstring> #include<string> #include<algorithm> #include<cstdio> using namespace std; const int maxn=4000+10; int a[maxn],b[maxn],c[maxn],d[maxn],sum1[maxn*maxn],sum2[maxn*maxn]; int len,sum; void init() { memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); memset(c,0,sizeof(c)); memset(d,0,sizeof(d)); memset(sum1,0,sizeof(sum1)); memset(sum2,0,sizeof(sum2)); } int check(int x) { int l=0,r=len-1,mid=0; while(l<=r) { mid=(l+r)/2; if(x==sum2[mid]) { int e=mid,w=0; while(x==sum2[e]&&e<len) { e++,w++; } e=mid-1; while(x==sum2[e]&&e>=0) { e--,w++; } return w; } else if(x<sum2[mid]) { r=mid-1; } else if(x>sum2[mid]) { l=mid+1; } } return 0; } int main() { init(); int n; scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%d %d %d %d",&a[i],&b[i],&c[i],&d[i]); } len=0; for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { sum1[len++]=a[i]+b[j]; } } len=0; for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { sum2[len++]=-(c[i]+d[j]); } } sort(sum2,sum2+len); sum=0; for(int i=0;i<len;i++) { int ans=check(sum1[i]); sum+=ans; } printf("%d\n",sum); }