UVA1152-4 Values whose Sum is 0

4 Values whose Sum is 0
Time limit: 9.000 seconds

The SUM problem can be formulated as follows: given four lists ABCD of integer values, compute how many

quadruplet (abcd ) $ \in$ 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 input begins with a single positive integer on a line by itself indicating the number of the cases following, each of them as described below. This line is followed by a blank line, and there is also a blank line between two consecutive inputs.

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 ABC and D .


Output 

For each test case, the output must follow the description below. The outputs of two consecutive cases will be separated by a blank line.

For each input file, your program has to write the number quadruplets whose sum is zero.


Sample Input 

  
  
1
6
-45 22 42 -16
-41 -27 56 30
-36 53 -37 77
26 -38 -10 62
-36 30 -75 -46
-32 -54 -6 45

Sample Output 

5

Sample Explanation:  Indeed, the sum of the five following quadruplets is zero: (-45, -27, 42, 30), (26, 30, -10, -46), 
(-32, 22, 56, -46),(-32, 30, -75, 77), (-32, -54, 56, 30).



题意:  给定4个n元素集合 A,B,C,D, 要求分别从中选取一个元素 a,b,c,d 使得 a + b + c + d = 0, 问有多少种选法.


算法分析:
    题目最容易想到的算法是 4 重循环枚举 a,b,c,d.判断加起来是否为 0.很显然,时间复杂度为O(n^4)必然超时,从而可以对当前算法进行优化,枚举 a,b,c,再去集合 D 中找是否存在一个元素 d 使得 d - a - b - c = 0.如果排序后用二分查找,时间复杂度则是O(n^3logn).可以将上述方法进一步推广,得到一个更快的算法.首先枚举所有 a+b,将结果存储在数组中或者哈希表中,然后枚举 -c-d 有多少个与 a+b 相同,从而时间复杂度变为O(n^2logn)


代码实现:

#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <iostream>
#include <math.h>
using namespace std;
const int Max = 4000 + 10;
int a[Max], b[Max], c[Max], d[Max];
int mem[Max*Max];


int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        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]);
        }
        int k = 0;
        for(int i = 0; i < n; i++)///将 a+b 的值存入数组中
        {
            for(int j = 0; j < n; j++)
            {
                mem[k++] = a[i] + b[j];
            }
        }
        sort(mem,mem+k);


        int ans = 0;
        for(int i = 0; i < n; i++)///将排序后的 a+b 的值进行二分查找,如果 a+b 与 (-c-d) 相同,则将结果加 1 .
            for(int j = 0; j < n; j++)
            {
                ans += upper_bound(mem,mem+k,-c[i]-d[j]) - lower_bound(mem,mem+k,-c[i]-d[j]);
            }
        printf("%d\n",ans);
        if(t)
            printf("\n");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值