poj 3274 哈希查找(黄金平衡)

Gold Balanced Lineup
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 14175 Accepted: 4109

Description

Farmer John's N cows (1 ≤ N ≤ 100,000) share many similarities. In fact, FJ has been able to narrow down the list of features shared by his cows to a list of onlyK different features (1 ≤ K ≤ 30). For example, cows exhibiting feature #1 might have spots, cows exhibiting feature #2 might prefer C to Pascal, and so on.

FJ has even devised a concise way to describe each cow in terms of its "feature ID", a single K-bit integer whose binary representation tells us the set of features exhibited by the cow. As an example, suppose a cow has feature ID = 13. Since 13 written in binary is 1101, this means our cow exhibits features 1, 3, and 4 (reading right to left), but not feature 2. More generally, we find a 1 in the 2^(i-1) place if a cow exhibits featurei.

Always the sensitive fellow, FJ lined up cows 1..N in a long row and noticed that certain ranges of cows are somewhat "balanced" in terms of the features the exhibit. A contiguous range of cowsi..j is balanced if each of the K possible features is exhibited by the same number of cows in the range. FJ is curious as to the size of the largest balanced range of cows. See if you can determine it.

Input

Line 1: Two space-separated integers, N and K.
Lines 2.. N+1: Line i+1 contains a single K-bit integer specifying the features present in cow i. The least-significant bit of this integer is 1 if the cow exhibits feature #1, and the most-significant bit is 1 if the cow exhibits feature # K.

Output

Line 1: A single integer giving the size of the largest contiguous balanced group of cows.

Sample Input

7 3
7
6
7
2
1
4
2

Sample Output

4
下面附上中文题目:

                    

解题思路:刚看到这个题就表示蒙了,完全不知道这个题是让干嘛的,后来仔细想可想,有点知道题目意思了,不过还是完全没有思路,于是就看了大神们的博客,这才知道是让干嘛的了。

首先这个题处理的数据范围比较大,所以用一般的循环查找肯定是超时,所以就要往哈希表上想,先判断其关键字,让后根据关键字来缩小范围继续进行查找,这样可以省不少时间。那么下面就来看看这个题的具体思路吧:

对于每头牛都有一个数字来表示,并且这头牛的属性使用二进制来表示的,其位数不超过k,

1、首先将输入的十进制数转化成二进制数并反向存储起来,二进制数的每一位表示该牛具有的属性;

2、根据转换的二进制数计算从第一头牛开始到该牛(即第i头牛)的每种属性出现次数的和;

3、然后让每一行(即每头牛的各个属性)的数减去第一个数,得出一个序列,如果两头牛之间是平衡区间的话,那么各个特征增长的数量是相等的,即得到的这个序列是相同的;

4、最后找出距离最远的两个相同序列,这个距离即是题解。

举个例子说明:

   x           属性           牛

   7          1 1 1            1

   6          0 1 1            2

   7          1 1 1            3

   2          0 1 0            4

   1          1 0 0            5

   4          0 0 1            6

   2          0 1 0            7

按行累加得sum[i]:

1 1 1

1 2 2

2 3 3

2 4 3

3 4 3

3 4 4

3 5 4

都减去第一列得c[i]:

0 0 0

0 1 1

0 1 1

0 2 1

0 1 0

0 1 1

0 2 1

所以说  最大区间是  6-2 = 4

不过最后我要说明一点,在计算hash关键字key时,由于我之前的编程习惯用的是 * (乘号),提交就毫不留情的超时了,所以此处要用移位运算符,这样很轻松的就过了。如果还有什么地方不懂的,代码中有详细注释。好了,不废话了,上代码:


具体代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100005
#define mod 1000000 //此处mod定义为99997时,运行时间1000多MS 
int hash[MAX*10];//hash表储存下标 
int sum[MAX][35];//第 1 头牛到第 i 头的对应属性的和 
int c[MAX][35];//存放每头牛属性 j与第一个属性的差 
int n,k;
int Hash_key(int *cc)
{
	int j,key=0;
	for(j=1;j<k;j++)
		key=key%mod+cc[j]<<2;//此处用 * 乘超时 
	key=abs(key)%mod;//此处得到的key可能会是负数,所以取绝对值 
	return key;
}
int main()
{
	int i,j,x,maxlen=0;//maxlen为最大长度 
	scanf("%d%d",&n,&k);
	memset(hash,-1,sizeof(hash));//初始化哈希表 
	hash[0]=0;//hash表首位初始化 
	for(i=1;i<=n;i++)
	{
		scanf("%d",&x);
		for(j=0;j<k;j++)
		{
			sum[i][j]=sum[i-1][j]+x%2;
			c[i][j]=sum[i][j]-sum[i][0];
			x>>=1;
		}
		int key=Hash_key(c[i]);
		while(hash[key]!=-1)//处理关键字冲突 
		{
			for(j=0;j<k;j++)//当前牛的属性与其关键字相同的进行比较 
				if( c[i][j]!=c[ hash[key] ][j] )
					break;
			if(j==k && maxlen<(i-hash[key]))//若j==k,说明两头牛的属性个数相同 
			{
				maxlen=i-hash[key];
				break;
			}
			key++;//往后继续移动处理冲突 
		}
		if(hash[key]==-1)
			hash[key]=i; //将下标存放在hash中 
	}
	printf("%d\n",maxlen);	
	return 0;
}


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值