hdu4334 trouble

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?
 

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;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值