您的位置:首页 > 产品设计 > UI/UE

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

2017-08-03 00:48 447 查看
问题描述: 给定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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: