POJ 2785 4 Values whose Sum is 0(排序+二分搜索)

Description
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 .
Input
The first line of the input file contains the size of the lists n (this value can be as large as 4000). We then have n lines containing four integer values (with absolute value as large as 228 ) that belong respectively to A, B, C and D .
Output
For each input file, your program has to write the number quadruplets whose sum is zero.
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

 

大致题意:给你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;
}

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值