HDU 4334 Trouble(hash + 枚举)

HDU 4334

题意:

给五个数的集合,问能否从每个集合中取一个数,使五个数之和为0.

思路:

集合大小是200,直接枚举的复杂度是200^5,一定会超时。

直接枚举的上限是3层,我们可以将枚举剩下两个集合各任取一个元素可能组成的元素和,并将其作hash处理,使我们能很快判断枚举出来的三个集合元素和在剩下的两个集合里是否有相应元素匹配。

code:

/*
* @author Novicer
* language : C++/C
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
#define INF 2147483647
#define cls(x) memset(x,0,sizeof(x))
#define rise(i,a,b) for(int i = a ; i <= b ; i++)
using namespace std;
const double eps(1e-8);
typedef long long lint;

const int maxn = 200 + 5;
const lint fix = 2*1e15 + 20;
const int key = 100003;
lint s[5][maxn];
lint table[key + 10];

int n;

bool check(){
	if(s[0][0] > 0 && s[1][0] > 0 && s[2][0] > 0 && s[3][0] > 0 && s[4][0] > 0)
		return false;
	if(s[0][n-1] < 0 && s[1][n-1] < 0 && s[2][n-1] < 0 && s[3][n-1] < 0 && s[4][n-1] < 0)
		return false;
	return true;
}

void addintohash(lint x){
    lint p = x % key;
    while(table[p] != -1 && table[p] != x){
        p ++;
        if(p == key) p = 0;
    }
    table[p] = x;
}
bool hash1(lint x){
    lint p = x % key;
    while(table[p] !=x && table[p] != -1){
        p ++;
        if(p == key) p = 0;
    }
    if(table[p] != x) return false;
    return true;
}
bool solve(){
	bool flag = false;
	for(int i = 0 ; i < n ; i++){
		for(int j = 0 ; j < n ; j++){
			for(int k = 0 ; k < n ; k++){
				lint tmp = s[0][i] + s[1][j] + s[2][k];
				if(tmp >= -fix && tmp <= fix && hash1(0 - tmp + fix)){
					flag = true;
					return true;
				}
			}
		}
	}
	return false;
}
int main(){
//	freopen("input.txt","r",stdin);
	int t; cin >> t;
	while(t--){
		memset(table,-1,sizeof(table));
		cin >> n;
		for(int i = 0 ; i < 5 ; i++){
			for(int j = 0 ; j < n ; j++){
				scanf("%I64d",&s[i][j]);
			}
			sort(s[i] , s[i]+n);
		}
		for(int i = 0 ; i < n ; i++){
			for(int j = 0 ; j < n ; j++){
				addintohash(s[3][i]+ s[4][j] + fix);
			}
		}
		if(!check()){
			cout << "No\n";
			continue;
		}
		else{
			if(solve()){
				cout << "Yes\n";
			}
			else{
				cout << "No\n";
			}
		}
		
	}
		
	return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值