八面码问题(BFS+Hash)

<pre name="code" class="cpp">#include<iostream>
#include<cstring>
#include<string>
#include<set>
#include<vector>
#include<queue>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
typedef int State[9];
const int maxn=1000000;
State st[maxn],goal;    //相当于st[maxn][9]保存走的每一步下的8个数字的;goal[9]保存目标;
int dist[maxn];   //距离,即走了几步;
const int dx[]={1,-1,0, 0};
const int dy[]={0, 0,1,-1};
bool inside(int x,int y)
{
<span style="white-space:pre">	</span>return x>=0&&x<3&&y>=0&&y<3;
}
int bfs()
{
	init_table();
	int front=1,rear=2;
	while(front<rear)     //就相当于queue
	{
		State& s=st[front];    //s就是st[front]的地址;
		if(!memcmp(s,goal,sizeof(s))) return front;
		int z;
		for(z=0;z<9;z++) if(!s[z]) break;
		int x=z/3,y=z%3;
		for(int i=0;i<4;i++)  //先走4步试试
		{
			int nx=dx[i]+x;
			int ny=dy[i]+y;
			int nz=nx*3+ny;
			if(inside(nx,ny))  //如果是合法的移动
			{
				State& t=st[rear];
				memcpy(t,s,sizeof(s));
				t[nz]=s[z];
				t[z]=s[nz];                   //保存rear这一步的状态
				dist[rear]=dist[front]+1;      //这一步的步数是上一步的+1;
				if(try_to_insert(rear)) rear++;    //判断这是否已经走过,若走过就走另一种路,并将其覆盖
			}
		}
			front++;   //front是判断每走的一步是否到达goal
	}	


} 

int main()
{
	for(int i=0;i<9;i++)
	cin>>st[1][i];
	for(int i=0;i<9;i++)
	cin>>goal[i];
	int idx=bfs();
	cout<<dist[idx];
	return 0;
}

关键是判重:
1)STL的set

set<int> lookup;
void init_table()
{
<span style="white-space:pre">	</span>lookup.clear();
}
bool try_to_insert(int n)
{
	int sum=0;
	State& t=st[n];
	for(int i=0;i<9;i++) sum=t[i]+sum*10;
	if(lookup.count(sum)) return false;
	lookup.insert(sum);
	return true;
}

2)Hash表
const int Hashsize=1000003;
int Head[maxn],next[maxn];
void init_table()
{
	memset(Head,0,sizeof(Head));
	memset(next,0,sizeof(next));
}
int Hash(int n)  //将9个数映射为符合Hashsize的数
{
	int v=0;
	State& t=st[n];
	for(int i=0;i<9;i++) v=t[i]+v*10;
	return v % Hashsize;
}
bool try_to_insert(int s)
{
	int h=Hash(s);  
	int u=Head[h];	// Head[h]保存st[s]中同样的Hash数的最前面的s位置
	while(u)  //非零就说明以前遇到过同样的hash值
	{
		if(!memcmp(st[s],st[u],sizeof(st[u]))) return false;
		u=next[u]; //next指向同样的hash数的前一个s值
	}
	next[s]=Head[h];  //当前s这一步指向下一个同样的hash数的s值即Head[h];
	Head[h]=s;       //当前hash数h指向s这一步,即更新到同样的Hash数的最前面的s位置;
	return true;
}


 
 
 

你可能感兴趣的:(八面码问题(BFS+Hash))