【洛谷P1379】八数码难题 状压bfs

对于这道题来说,每个时刻的状态是整个棋盘所有棋子的位置,即:任何一个棋子位置发生了移动,都会使得状态转移。
因此,需要采取将整个状态作为广搜的搜索对象,进行状态压缩。采用哈希得到每个状态的对应的数值,同时维护一个 map 判重即可,顺便记录走到当前状态所需的最短步数。

代码如下

#include <bits/stdc++.h>
using namespace std;
const int dx[]={0,0,1,-1};
const int dy[]={1,-1,0,0};
const int ed=123804765;

int st,a[4][4],nx,ny;
map<int,int> mp;
queue<int> q;

void change(int x){
	for(int i=3;i>=1;i--)
		for(int j=3;j>=1;j--){
			a[i][j]=x%10,x/=10;
			if(!a[i][j])nx=i,ny=j;
		}
}

int get_hash(){
	int tot=0;
	for(int i=1;i<=3;i++)
		for(int j=1;j<=3;j++)
			tot=tot*10+a[i][j];
	return tot;
}

void bfs(){
	scanf("%d",&st);
	q.push(st);
	mp[st]=0;
	while(q.size()){
		int u=q.front();q.pop();
		if(u==ed)break;
		change(u);
		for(int i=0;i<4;i++){
			int x=nx+dx[i],y=ny+dy[i];
			if(x<1||y<1||x>3||y>3)continue;
			swap(a[x][y],a[nx][ny]);//改变状态
			int v=get_hash();//得到新的哈希值
			if(!mp.count(v)){
				mp[v]=mp[u]+1;
				q.push(v);
			}
			swap(a[x][y],a[nx][ny]);//复原之前的状态
		}
	}
	printf("%d\n",mp[ed]);
}

int main(){
	bfs();
	return 0;
}
posted @ 2018-11-06 21:53  shellpicker  阅读(269)  评论(0编辑  收藏  举报