Trouble
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3791 Accepted Submission(s): 1191
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?
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
比赛的时候做的一题,一直超时,我以为是重复数据太多导致的,所以就用了用set判重,结果还是超时,比赛完了看了解题报告重新写了一遍,果真过了,连剪枝都用不上,然后我又把重复的结果去掉了,时间才缩短了70毫秒,哎。。终于知道之前为什么超时了
查找的时候要用到一种方法:
事实上考虑如下问题,快速求解序列A,序列B中,是否有Ai+Bj=x ,记得是某知名公司的一道面试题吧;
是两个指针的应用,将A,B升序排列,初试 i 指针指向A[1] ,j 指针指向 B[b_size] ,比较Ai + Bj 与 x 的
大小。若A[i]+B[j]<x , i 指针右移 ; 若 A[i]+B[j]>x , j 指针左移 。
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
__int64 num[5][210],a[40000],b[40000],temp;
int main()
{
int t,j,i,n,k,m,flag,len1,len2,len3;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=0;i<5;i++)
{
for(j=0;j<n;j++)
{
scanf("%I64d",&num[i][j]);
}
}
for(i=0,k=0;i<n;i++)
{
for(j=0;j<n;j++)
{
a[k++]=num[0][i]+num[1][j];
}
}
sort(a,a+k);
for(i=1,j=0;i<k;i++)//这是去重用的,可以忽视,这题重复数据不多,下面的也是一样
{
if(a[j]!=a[i])
a[++j]=a[i];
}
len1=j+1;
//for(i=0,j=0;i<k;i++)
//printf("%d ",a[i]);
for(i=0,m=0;i<n;i++)
{
for(j=0;j<n;j++)
{
b[m++]=num[2][i]+num[3][j];
}
}
sort(b,b+m);
for(i=1,j=0;i<m;i++)
{
if(b[j]!=b[i])
b[++j]=b[i];
}
len2=j+1;
sort(num[4],num[4]+n);
for(i=1,j=0;i<n;i++)
{
if(num[4][j]!=num[4][i])
num[4][++j]=num[4][i];
}
len3=j+1;
for(i=0,flag=0;i<len3;i++)
{
j=0;
k=len2-1;
while(j<len1&&k>=0)//这一步就要用到那种方法了
{
temp=a[j]+b[k];//printf("%I64d ",num[4][i]);
if(temp+num[4][i]>0)
k--;
else if(temp+num[4][i]<0)
j++;
else
{
flag=1;
break;
}
}
if(flag)
break;
}
if(flag)
printf("Yes\n");
else printf("No\n");
}
return 0;
}