POJ 3274 Gold Balanced Lineup(哈希表)

题目链接:Gold Balanced Lineup

解题思路:这道题看了解题报告之后才做出来,先将每一位的1或0累加起来做一个sum[i][j],表示第i头牛的j属性累加到现在的和。那么如果在这个区间里面每种属性出现的次数相同的话就表明sum[i][k] - sum[j][k] = sum[i][1] - sum[j][1]变形一下就得到 sum[i][k] - sum[i][1] = sum[j][k] - sum[j][1]那么k位就可以生成k - 1个数组成的‘特征’序列,只要这两个序列相等那么算一下下标差,取最大值就好了。容易错的地方就是边界问题如这组数据4 4 1 2 4 8,应该为4,所以要在之前插入一个0牛,所有数据都是0。还有就是如果只有1头牛就能满足所有属性出现一次,而且其他的答案均不满足,这时是1不是0。

PS:个人感觉hash的题目就是最终还是在众多数据里面找到两个或者多个相同的数据,数据形式可能是多样的。但是每一个hash的问题到最后都会简化成这个基础问题。难点就只是前面的问题简化是否可以想得出来。再者就是计算HASH值得时候,好方法很多,对于时间复杂度影响很大,还需好好学习。

#include
#include
#include 
#include
#define MAX 100000
#define FI 99991

using namespace std;

struct A{
	int num[32];
};
typedef struct A node;

vector cow[MAX];
int sum[32];

int main(){
	int i, j, k, n, tem, hash, ans, tot, key; 
	node s; 
	//freopen("in.txt", "r", stdin); 
	while(scanf("%d%d", &n, &k) != EOF){
		ans = 0;
		key = 0;
		for(i = 0; i < MAX; i++){
			cow[i].clear();
		}
		memset(sum, 0, sizeof(sum));
		memset(s.num, 0, sizeof(s.num));
		cow[0].push_back(s);
		for(i = 1; i <= n; i++){
			scanf("%d", &tem);
			tot = hash = 0;
			for(j = 0; j < k; j++){
				tem >>= j == 0 ? j : 1;
				if(tem & 1){
					sum[j]++;
					tot++;
				}
				if(tot == k)	key = 1;
				if(j > 0){
					s.num[j] = sum[j] - sum[0];
					hash += s.num[j] * j; 
				}
			}
			s.num[0] = i;
			hash = abs(hash) % FI;
			for(j = 0; j < cow[hash].size(); j++){
				int flag = 1;
				for(int g = 1; g < k; g++){
					if(cow[hash][j].num[g] != s.num[g]){
						flag = 0;
						break;
					}
				}
				if(flag){
					ans = (s.num[0] - cow[hash][j].num[0]) > ans ? s.num[0] - cow[hash][j].num[0] : ans;
				}
			}
			cow[hash].push_back(s);
		}
		if(ans)
			printf("%d\n", ans);
		else
			printf("%d\n", key);	
	}
	return 0;
}


 

你可能感兴趣的:(数据结构,STL)