5
大致题意:给你A,B,C,D四个数组,在A,B,C,D中各找一个数,使其和为0,求出种数(另外同一数组中相同数值的看成不同数);
解题思路:这一题大家相信首先想到的是否可以通过枚举得出答案?如果正常枚举的话看一下n的大小,高达4000,时间复杂度为O(n^4);接着我们来看如何降低时间复杂度!首先我们有a+b+c+d=0可得,只要a,b,c确定的话d=-(a+b+c),就是说d随之确定。我们只要查找
-(a+b+c)是否存在于D中即可,可以先对D排序,再二分查找实现。先这样优化一下时间复杂度降为O(n*n*n*log(n));这样时间复杂度还是不行的。还要接着优化。最终我们该把A,B合为一组,C,D合为一组,A,B的组合n*n种,C,D的组合有n*n种,并存储c+d,再排序。当确定a+b的和时(有n*n种)接着从c+d中二分寻找-(a+b)的值即可,另外可能存在多个值等于-(a+b),这时要稍做处理。
AC代码:
# include <cstdio> # include <algorithm> using namespace std; int a[4010], b[4010], c[4010], d[4010]; int c_add_d[16000010]; int main(){ int n, i, j, k, ans, des, left, right, temp, mid, l; while(scanf("%d", &n)!=EOF){ if(n==0){ printf("0\n"); continue; } for(i=1; i<=n; i++){ scanf("%d%d%d%d", &a[i], &b[i], &c[i], &d[i]); } k=1; for(i=1; i<=n; i++){ for(j=1; j<=n; j++){ c_add_d[k++]=c[i]+d[j]; } } sort(c_add_d+1, c_add_d+k); ans=0; for(i=1; i<=n; i++){ for(j=1; j<=n; j++){ left=1; right=k-1; des=-(a[i]+b[j]); while(left<=right){ mid=(left+right)/2; if(c_add_d[mid]==des){ ans++; for(l=mid+1; l<=k-1; l++){ if(c_add_d[l]==des){ ans++; } else{ break; } } for(l=mid-1; l>=1; l--){ if(c_add_d[l]==des){ ans++; } else{ break; } } break; } else if(c_add_d[mid]>des){ right=mid-1; } else{ left=mid+1; } } } } printf("%d\n", ans); } return 0; }