hdu 6046 hash

题:

  OwO http://acm.hdu.edu.cn/showproblem.php?pid=6046

  (2017 Multi-University Training Contest - Team 2 - 1002)  

 

解:

  设A矩阵为1e3*1e3的那个矩阵,另一个叫B矩阵

  首先对A矩阵进行预处理,每一行中的每一个点的哈希值为这个点和其右边63个点的组合值(总计64个点)(如果右边没63个点了那就不做了),放入hashmap中

  然后对B矩阵进行扫描。

  想象把很多个A矩阵铺在B矩阵上面,使A矩阵有预处理的部分铺满B矩阵

  那么对B矩阵每1000行枚举一行,每900列枚举一列,则这些行列的交叉点钟必然有一个点存在于A矩阵中。

  由这个点的哈希值(就是前文说的该点对应的64个点的组合值)那么找出这个点,并且由hashmap得知这个点在A矩阵中的位置,就可以得知A矩阵在B矩阵中的具体位置。

  (思路来源为某其他博客)

 

 

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

typedef unsigned long long ll;

const ll hashM=1200044;
const ll hashmod=1442441;
ll hashval[hashM],hashtol;
int hashnxt[hashM],hashpos[hashM],hashid[hashmod];

void hashInit()
{
	hashtol=0;
	memset(hashid,0,sizeof(hashid));
}

void hashInsert(ll val,int pos)
{
	int tmp=val%hashmod;
	hashtol++;
	hashval[hashtol]=val;
	hashpos[hashtol]=pos;
	hashnxt[hashtol]=hashid[tmp];
	hashid[tmp]=hashtol;
}

int hashFindpos(ll val)
{
	int tmp=val%hashmod;
	for(int i=hashid[tmp];i;i=hashnxt[i])
		if(hashval[i]==val)
			return hashpos[i];
	return -1;
}

const int N=1000;
const int M=1044;
const int bas=1024;
const int cps=64;
char s[M][M];

inline unsigned sfr(unsigned h, unsigned x) 
{
	return h >> x;
}

int f(ll i, ll j) 
{
	ll w = i * 1000000ll + j;
	int h = 0;
	for(int k = 0; k < 5; ++k) 
	{
		h += (int) ((w >> (8 * k)) & 255);
		h += (h << 10);
		h ^= sfr(h, 6);
	}
	h += h << 3;
	h ^= sfr(h, 11);
	h += h << 15;
	return sfr(h, 27) & 1;
}

ll hashtmp[M];

bool check(int x0,int y0)
{
	int i,j;
	for(i=1;i<=N;i++)
		for(j=1;j<=N;j++)
			if(f(x0+i-1,y0+j-1)!=(s[i][j]-'0'))
				return false;
	return true;
}

void solve(int cas)
{
	int i,j,k,x,y,tmp,x0,y0;
	ll tmpval;
	for(i=0;i<1000;i++)	//1000
		for(j=0;j<=1111;j++)	//900
		{
			tmpval=0;
			for(k=1;k<=cps;k++)
				tmpval=(tmpval<<1)+f(i*1000+1,j*900+1+k-1);
			tmp=hashFindpos(tmpval);
			if(tmp!=-1)
			{
				y=tmp%bas; x=(tmp-y)/bas;
				x0=i*1000+1; y0=j*900+1;
				x0-=(x-1); y0-=(y-1);
				if(check(x0,y0))
				{
					printf("Case #%d :%d %d\n",cas,x0,y0);
					return ;
				}
			}
		}
}

int main()
{
	int T,tmp,i,j,k;
	ll tmpval;
	cin>>T;
	for(int cas=1;cas<=T;cas++)
	{
		hashInit();
		for(i=1;i<=N;i++)
			scanf("%s",s[i]+1);
		for(i=1;i<=N;i++)
		{
			hashtmp[0]=0;
			for(j=1;j<=N;j++)
				hashtmp[j]=(hashtmp[j-1]<<1)+(s[i][j]-'0');
			for(j=1;j+cps-1<=N;j++)
				hashInsert(hashtmp[j+cps-1],i*bas+j);
		}
		solve(cas);
	}
	return 0;
}

  

 

posted @ 2017-07-29 15:11  太阳星人FxxL  阅读(511)  评论(9编辑  收藏  举报