uva 1152 和为0的4个值(中途相遇法)

Sum为0的值SUM问题可以表示如下:给定四个列表A,B,C,D的整数值,计算多少个四元组(a,b,c,d)∈A×B×C× D是这样的a + b + c + d = 0.

在下文中,我们假设所有列表具有相同的大小n。输入输入以一行上的单个正整数开始,表示后面的案例数,每个案例如下所述。该行后面是一个空行,两个连续输入之间也有一个空行。输入文件的第一行包含列表n的大小(此值可以大到4000)。然后,我们有n行包含四个整数值(绝对值大到2 28),它们分别属于A,B,C和D.输出对于每个测试用例,程序必须写入总和为零的四元组数。两个连续案例的输出将用空行分隔。

样品输入1

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

样品说明:的确,以下五个四联体的总和为零:( - 45,-27,42,30),(26,30,-10,-46),( - 32,22,56,-46),( - 32, 30,-75,77),( - 32,-54,56,30)。

题解:

题目不难,思想也可以,希望下次遇到同类型的题目会做。
如果用四重循环会超时,所以中途相遇法二分成  a+b =  -(c+d),   只用两重循环加上一个二分查找就可以解决问题。

关于lower_bound和upper_bound的用法:在从小到大的排序数组中,

lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

源代码:
 

#include <iostream>
#include <algorithm>
#define maxn 4005
using namespace std;

int t, n, a[maxn], b[maxn], c[maxn], d[maxn], sum[maxn*maxn];

int main() {
	cin >> t;
	while(t--) {
		cin >> n;
		for(int i = 0; i < n; ++i) scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);//C语言输入
		int k = 0, ans = 0;
		for(int i = 0; i < n; ++i)
			for(int j = 0; j < n; ++j)
				sum[k++] = a[i] + b[j];
				sort(sum, sum + k);
		for(int i = 0; i < n; ++i)
			for(int j = 0; j < n; ++j)
				ans+=upper_bound(sum,sum + k,-c[i]-d[j]) - lower_bound(sum, sum + k, -c[i]-d[j]);
		cout << ans ;
		if(t) cout << endl << endl;
	}
	return 0;
}

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值