码迷,mamicode.com
首页 > 其他好文 > 详细

HDU ACM 1067 Gap->BFS+HASH判重

时间:2015-06-07 09:45:12      阅读:263      评论:0      收藏:0      [点我收藏+]

标签:c   c++   acm   编程   算法   

题意:初始状态为左边空一行,数字在右边28个格子。末态要按一副卡片在一行顺序牌,即第一行为11-17,第二行21-27,。。。。,可以通过四个空格来转移卡片,问从初始状态到末态最少要多少步。

分析:

1、每次操作只能把一个数字放到某个空格,不能交换两个数字的位置。

2、用的是再哈希法hash =(v+10)%M来处理冲突。

3、空格的左边为空或者数字的末尾为7则不能填充。

4、填充空格要找比他左边大1的数来填充。

#include<iostream>
#include<queue>
using namespace std;

#define MOD 1000007
__int64 Hash[1000007];   //hash表,用于hash判重

struct Node
{
	int map[4][8];    //图
	int step;         //步数
	bool operator==(const Node& p)const  //判断相等
	{
		int i,j;

		for(i=0;i<4;i++)
			for(j=0;j<8;j++)
				if(map[i][j]!=p.map[i][j])
					return false;
		return true;
	}
	__int64 HashValue()  //hash值
	{
		__int64 v=0;
		int i,j;

		for(i=0;i<4;i++)
			for(j=0;j<8;j++)
				v+=(v<<1)+map[i][j];
		return v;
	}
};

Node s,e;    //初始节点和结束节点

void Swap(int& a,int& b)
{
	int tmp;

	tmp=a;
	a=b;
	b=tmp;
}

void Read()
{
	int i,j;

	memset(Hash,-1,sizeof(Hash));
	for(i=0;i<4;i++)               //初始第0列为空
	{
		s.map[i][0]=0;
		for(j=1;j<8;j++)
			scanf("%d",&s.map[i][j]);
	}
	s.step=0;
}

void GetEnd()    //获得终态
{
	int i,j;

	for(i=0;i<4;i++)
	{
		e.map[i][7]=0;
		for(j=0;j<7;j++)
			e.map[i][j]=(i+1)*10+(j+1);
	}
}

bool HashJudge(__int64 value)  //hash判重
{
	int v;

	v=value%MOD;
	while(Hash[v]!=-1 && Hash[v]!=value)  //冲突处理,在hash法
	{
		v+=10;
		v%=MOD;
	}
	if(Hash[v]==-1)
	{
		Hash[v]=value;
		return true;
	}
	return false;
}

bool bfs(int& ans)
{
	queue<Node> q;
	Node p,p2;
	int i,j,x,y,value,k,l;
	bool fg;
	__int64 ha;

	q.push(s);                 //初始节点入队
	HashJudge(s.HashValue());
	while(!q.empty())
	{
		p=q.front();
		q.pop();
		for(i=0;i<4;i++)
			for(j=0;j<8;j++)
			{
				if(!p.map[i][j])  //格子为空
				{
					p2=p;
					p2.step++;
					value=p.map[i][j-1]+1;  //找比map[i][j-1]大1的数
					if(value==1||value%10==8) //0或者value为7的不能移动
						continue;
					fg=true;
					for(k=0;k<4&&fg;k++)
						for(l=1;l<8&&fg;l++)
							if(p.map[k][l]==value)
							{
								x=k;
								y=l;
								fg=false;
							}
					if(!fg)
					{
						Swap(p2.map[i][j],p2.map[x][y]);
						ha=p2.HashValue();
						if(HashJudge(ha))   //hash判重
						{
							if(p2==e)
							{
								ans=p2.step;
								return true;
							}
							q.push(p2);
						}
					}
				}
			}
	}
	return false;
}

void Process()
{
	int k,i,j,ans;

	k=0;
	for(i=0;i<4;i++)   //初始时将11,21,31,41移动到第0列
		for(j=1;j<8;j++)
			if(s.map[i][j]==(k+1)*10+1)
			{
				Swap(s.map[i][j],s.map[k][0]);
				k++,i=0,j=0;
			}
	if(s==e)
	{
		cout<<0<<endl;  //前四步不记录
		return ;
	}
	if(bfs(ans))
		cout<<ans<<endl;
	else
		cout<<-1<<endl;
}

int main()
{
	int T;

	scanf("%d",&T);
	GetEnd();
	while(T--)
	{
		Read();
		Process();
	}
    return 0;
}


HDU ACM 1067 Gap->BFS+HASH判重

标签:c   c++   acm   编程   算法   

原文地址:http://blog.csdn.net/a809146548/article/details/46390375

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!