POJ2785 -- 4 Values whose Sum is 0(折半枚举)


问题描述: 给定4个数组ABCD从每个数组中选出1个数abcd,使得a+b+c+d=0 每个数组中相同的数组看做不同的情况,因此本题不需要进行剪枝。


思路:如果对每个数组的数字进行枚举,那么时间复杂度为n^4,但虽然本题的时长可以为15000ms,也会导致超时。

但如果折半来看,枚举2个数组的复杂度为n^2,剩下的2个数组使用二分法来进行计算 那么时间复杂度就为n^2logn 就可以接受。

首先枚举ab2个数组的n^2个情况  由于a+b+c+d=0 也就是说 a+b = -c - d

那么我们只需要在cd中选出2个数值为ai + bj即可。

lower_bound()返回第一次出现某个数的指针

upper_bound()返回最后一次出现某个数的指针

那么upper_bound() - lower_bound()就是出现某个数的次数

到这里也发现这里的折半枚举跟传统意义上的折半枚举不同 只是应用了它的思想 把问题分成2半来考虑.


代码:

#include <cstdio>
#include <cstring>
#include <algorithm>


using namespace std;
int a[4000 + 5];
int b[4000 + 5];
int c[4000 + 5];
int d[4000 + 5];
int ab[4005 * 4005];
int main()
{
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]);
}
for(int i = 0;i<n;i++)
{
for(int j = 0;j<n;j++)
{
ab[i*n+j] = a[i] + b[j];
}
}
sort(ab,ab+n*n);
long long ans = 0;
for(int i = 0 ;i<n;i++)
{
for(int j = 0 ;j<n;j++)
{
int cd = -(c[i] + d[j]);
ans += upper_bound(ab,ab+n*n,cd) - lower_bound(ab,ab+n*n,cd);
}
} 
printf("%lld\n",ans);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值