hdu4334 Trouble

Trouble

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 874    Accepted Submission(s): 270


Problem Description
Hassan is in trouble. His mathematics teacher has given him a very difficult problem called 5-sum. Please help him.
The 5-sum problem is defined as follows: Given 5 sets S_1,...,S_5 of n integer numbers each, is there a_1 in S_1,...,a_5 in S_5 such that a_1+...+a_5=0?
 

 

Input
First line of input contains a single integer N (1≤N≤50). N test-cases follow. First line of each test-case contains a single integer n (1<=n<=200). 5 lines follow each containing n integer numbers in range [-10^15, 1 0^15]. I-th line denotes set S_i for 1<=i<=5.
 

 

Output
For each test-case output "Yes" (without quotes) if there are a_1 in S_1,...,a_5 in S_5 such that a_1+...+a_5=0, otherwise output "No".
 

 

Sample Input
2
2
1 -1
1 -1
1 -1
1 -1
1 -1
3
1 2 3
-1 -2 -3 
4 5 6
-1 3 2
-4 -10 -1
 
Sample Output
No
Yes
 
小技巧: 给定两个有序集合X、Y分别有 x 和 y 个元素,在 X 中选择一个 a ,在 Y 中选择一个 b ,使得 a+b=c,c是给定的;可以在 O(x+y)时间内完成
 
题意:给你5个集合,每个集合都有 n 个元素,从这5个集合中每个集合选择一个元素,如果这5个元素和为 0 ,则输出Yes ,否则输出No。
分析:问题简化一下给定两个有序集合X、Y分别有 x 和 y 个元素,问在 X 中选择一个 a ,在 Y 中选择一个 b ,使得 a+b=c,c是给定的;
上面问题的可以再 O(x+y)时间内完成,定义两个指针 px 、py ;px 指向X中的第一个元素,py 指向Y中最后一个元素;
if   X(px)+Y(py)==c return true
if   X(px)+Y(py)<c  px++
if   X(px)+Y(py)>c  py--
 
上面问题解决了,那么五个集合问题也就好办了,第一和第二个集合 合成一个新集合1,第三和第四集合 合成一个新集合2, n^2个元素,
依次枚举第五个集合中的元素,是否在新集合1 和 新集合2 中,时间复杂度为O(n^3);
 
心得:比赛时写的是O(n^3 log n^2)的程序,持续TLE
 
View Code
 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5 #define MAXN 40010
 6 #define MAXM 210
 7 
 8 using namespace std;
 9 
10 long long sum1[MAXN],sum2[MAXN],num[5][MAXM];
11 int cnt;
12 
13 bool work(int n)
14 {
15     int p1,p2,k;
16     long long key;
17     for(k=0;k<n;k++)
18     {
19         key=-num[4][k];
20         p1=0;p2=cnt-1;
21         while(p1<cnt&&p2>=0)
22         {
23             if(sum1[p1]+sum2[p2]==key) return true;
24             else if(sum1[p1]+sum2[p2]<key) p1++;
25             else p2--;
26         }
27     }
28     return false;
29 }
30 
31 int main()
32 {
33     int test,i,j,n;
34     scanf("%d",&test);
35     while(test--)
36     {
37         scanf("%d",&n);
38         for(i=0;i<5;i++) for(j=0;j<n;j++)
39         {
40             scanf("%I64d",&num[i][j]);
41         }
42         cnt=0;
43         for(i=0;i<n;i++) for(j=0;j<n;j++)
44         {
45             sum1[cnt++]=num[0][i]+num[1][j];
46         }
47         cnt=0;
48         for(i=0;i<n;i++) for(j=0;j<n;j++)
49         {
50             sum2[cnt++]=num[2][i]+num[3][j];
51         }
52         sort(sum1,sum1+cnt);
53         sort(sum2,sum2+cnt);
54         if(work(n)) printf("Yes\n");
55         else printf("No\n");
56     }
57     return 0;
58 }

 

转载于:https://www.cnblogs.com/zhourongqing/archive/2012/08/02/2620757.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值