题目链接:http://poj.org/problem?id=2785
大意是输入一个n行四列的矩阵,每一列取一个数,就是四个数,求有多少种着四个数相加和为0的情况
首先脑海里想到的第一思维必然是一个个枚举,用四个for循环,那时间复杂度变成了On4,n的最大值是4000.
肯定会超时。那么,为了简化时间,首先我们可以开两个至少4000*4000的数组分别把第一列与第二列的和的情况
,第三列与第四列的和的情况存起来。这样就只用考虑两个数组的情况。
然后把两个数组排序,一个数组从头部开始同时另一个数组从尾部开始讨论和为0的情况(利用了递增性质和递减性质)
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 int a[4001],b[4001],c[4001],d[4001]; 5 int ab[4000*4000+1],cd[4000*4000+1]; 6 int main() 7 { 8 int n,i,j,k,num,sum,x; 9 while (~scanf("%d",&n)) 10 { 11 for (i=0;i<n;i++) 12 scanf("%d %d %d %d",&a[i],&b[i],&c[i],&d[i]); 13 k=0; 14 for (i=0;i<n;i++){ 15 for (j=0;j<n;j++) 16 ab[k++]=a[i]+b[j]; 17 } 18 k=0; 19 for (i=0;i<n;i++){ 20 for (j=0;j<n;j++) 21 cd[k++]=c[i]+d[j]; 22 } 23 sort(ab,ab+n*n); 24 sort(cd,cd+n*n); 25 x=n*n-1;sum=0; 26 for (i=0;i<n*n;i++) 27 { 28 while (x>=0&&ab[i]+cd[x]>0) 29 x--; 30 if (x<0) 31 break; 32 num=x; 33 while (ab[i]+cd[num]==0&&num>=0) 34 { 35 sum++; 36 num--; 37 } 38 } 39 printf("%d\n",sum); 40 } 41 return 0; 42 }
二分也很简单,找到相等个数就行
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 int a[4001],b[4001],c[4001],d[4001]; 6 int ab[4000*4000+1],cd[4000*4000+1]; 7 int k2; 8 int check(int x) 9 { 10 int left=1,right=k2-1,mid; 11 while (left<=right) 12 { 13 mid=(left+right)/2; 14 if (x==cd[mid]) 15 { 16 int w=0,e=mid; 17 while (x==cd[e]&&e<k2) 18 e++,w++; 19 e=mid-1; 20 while (x==cd[e]&&e>0) 21 e--,w++; 22 return w; 23 } 24 else if (x<cd[mid]) 25 right=mid-1; 26 else 27 left=mid+1; 28 } 29 return 0; 30 } 31 int main() 32 { 33 int t,i,j,q; 34 while (~scanf("%d",&t)) 35 { 36 for (i=1;i<=t;i++) 37 scanf("%d %d %d %d",&a[i],&b[i],&c[i],&d[i]); 38 memset(ab,0,sizeof(ab)); 39 memset(cd,0,sizeof(cd)); 40 int k1=1,sum=0; 41 k2=1; 42 for (i=1;i<=t;i++) 43 { 44 for (j=1;j<=t;j++) 45 { 46 ab[k1++]=a[i]+b[j]; 47 cd[k2++]=-(c[i]+d[j]); 48 } 49 } 50 sort(cd+1,cd+k2); 51 for (i=1;i<k1;i++) 52 sum+=check(ab[i]); 53 printf("%d\n",sum); 54 } 55 return 0; 56 }