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

版权声明:博主表示授权一切转载:)

时间: 2024-10-17 06:31:48

HDU 4334 Trouble(hash + 枚举)的相关文章

HDU 4334——Trouble——————【贪心&amp;水题】

Trouble Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5388    Accepted Submission(s): 1494 Problem Description Hassan is in trouble. His mathematics teacher has given him a very difficult pro

HDU 4334 Trouble

合并排序再枚举. 题意问五个数组中各抽一个加起来 和是否为 0. 开始想用 200*200*200 和 200*200 比.果然TLE了. 后来知道 得 200*200,200*200 ,200 . 先200*200 的枚举,排序,去重.然后三个元素加起来,微调 两个 200*200 的指针. 这题用 %lld 就WA.得用 %I64d .贡献N多TLE.N多WA.怒刷存在感. #include<cstdio> #include<cstring> #include<strin

HDU 4334 Trouble(哈希|线性查找)

给定五个集合,问能否从五个集合各取一个元素,使得元素之和为0. 这道题有两种做法,一种是哈希,然而之前没写过哈希.....比赛后从大神那copy了一份. 这里说另一种, 对于这五个集合分为三组,1,2组求和为一组,3,4组求和分为一组,5为一组. 那么现在转化为了能否从前两组中各取一个元素,使得这两个值和为第三组一个元素的绝对值. 那么对于第一组我们升序排序,第二组我们降序排序. 对于第三组里的任一元素,假如第一组队首加第二组队首之和大于第三组的元素,那么第二组游标往后移一位,反之第一组移一位,

HDU 4334 Trouble (暴力)

题意:给定五个集合,每个集合有n个数,从每个集合各取一个数使和为0.如果能输出Yes,不能则输出No. 看了网上的题解有很多解法,个人感觉这题暴力就能过. 首先将一二两个集合合并为数组a,再将三四两个集合合并数组b,然后进行从小到大排序, 设第五个数组为数组c,依次遍历c中的每一个数,看在a,b中是否存在两个数的和与c中的数的和为0, 将数组a,b进行sort排序,然后一个正序即从小到大遍历,一个逆序从大到小遍历, 如果三个数的和小于0,a数组后移一位,否则b后移一位. 这题WA了两次,第一次W

HDOJ4886(hash+枚举)

http://acm.hdu.edu.cn/showproblem.php?pid=4886 思路是队友想出来的,代码我写. 因为只有8个字母,容易证明答案只会在长度为8之内.长于8的因为可以用长度n+8得到,所以不存在.从长度1到8依次枚举所有原串中的子串,并将此串当成8进制存在哈希表中,每次枚举前都将哈希表置空,而后再从小到大遍历哈希表,将第一个没用过的下标换算为字符串输出,当位数不够时注意前导0处加‘A’. 1 #include<iostream> 2 #include<stdio

hdu 4941 STL HASH 模拟

http://acm.hdu.edu.cn/showproblem.php?pid=4941 比赛的时候现学的map的find...以前都是用下标做的,但是map用下标查询的话,如果查询的元素不存在,会插入一个新的元素. 贴一个map查找元素找到和找不到的模板 map<pair<int,int>,int>::iterator it=poshash.find(tmppos);//pair<int,int>poshash; int pp; if(it == poshash.

HDU 3709 Balanced Number 枚举+数位DP

枚举支点之后数位DP,注意姿势 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #include <list&g

HDU 4821 (hash)

这道题最重要的不仅是hash这种算法,更要学会利用好STL中的<map>才行. 将连续的L个字符经过hash赋值,最后线性判断.其中的判断步骤用到了map的插入特性. #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <map> using namespace std; #define maxn 500010 #

Trouble HDU - 4334

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 t