八数码

来源:互联网 发布:原生js点击事件 编辑:程序博客网 时间:2024/04/29 08:23



问题描述:

编号为1~8的8个正方形滑块被摆成3行3列(有一个格子留空)。每次可以把与空格相邻的滑块(有公共边才算相邻)移到空格中,而它原来的位置就成为了新的空格。给定初始局面和目标局面(用0表示空格),你的任务是计算出最少的移动步数。如果无解,输出-1。

样例输入:

2 6 4 1 3 7 0 5 8

8 1 5 7 3 6 4 0 2


样例输出:

31


方法一(bfs):


#include <cstdio>#include <cstring>#include <cstdlib>#include <string>#include <map>#include <cmath>#include <queue>#include <stack>#include <iostream>#include <stdexcept>#include <cstddef>#include <algorithm>#include <vector>#include <numeric>#include <cctype>#define LL long long#define Endl endl#define INF 0x7fffffff//#define WJusing namespace std;typedef int State[9];const int maxstate=1000000;State st[maxstate],goal;int dist[maxstate];const int dx[4]={-1,1,0,0};const int dy[4]={0,0,-1,1};int vis[362880],fact[9];void init(){fact[0]=1;for(int i=1;i<9;i++)fact[i]=fact[i-1]*i;}int try_to_insert(int s){int code=0;for(int i=0;i<9;i++){int cnt=0;for(int j=i+1;j<9;j++)if(st[s][j]<st[s][i])cnt++;code+=fact[8-i]*cnt;}if(vis[code]) return 0;return vis[code]=1;}int bfs(){init();int front=1,rear=2;while(front<rear){State& s=st[front];if(memcmp(goal,s,sizeof(s))==0) return front;int z; for(z=0;z<9;z++)if(!s[z]) break;int x=z/3,y=z%3;for(int d=0;d<4;d++){int newx=x+dx[d];int newy=y+dy[d];int newz=newx*3+newy;if(newx>=0&&newx<3&&newy>=0&&newy<3){State& t=st[rear];memcpy(&t,&s,sizeof(s));t[newz]=s[z];t[z]=s[newz];dist[rear]=dist[front]+1;if(try_to_insert(rear)) rear++;}}front++;}return 0;}int main(int argc, char *argv[]){#ifdef WJ//freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#endiffor(int i=0;i<9;i++)scanf("%d",&st[1][i]);for(int i=0;i<9;i++)scanf("%d",&goal[i]);int ans=bfs();if(ans>0) printf("%d\n",dist[ans]);else printf("-1\n");return 0;}



方法二(哈希):


#include <cstdio>#include <cstring>#include <cstdlib>#include <string>#include <map>#include <cmath>#include <queue>#include <stack>#include <iostream>#include <stdexcept>#include <cstddef>#include <algorithm>#include <vector>#include <numeric>#include <cctype>#define LL long long#define Endl endl#define INF 0x7fffffff//#define WJusing namespace std;typedef int State[9];const int hashsize=1000003;;int head[hashsize],next[hashsize];const int dx[]={-1,1,0,0};const int dy[]={0,0,-1,1};State st[hashsize],goal;int dis[hashsize];int hash(State& s){int v=0;for(int i=0;i<9;i++)v=v*10+s[i];return v%hashsize;}int try_to_insert(int s){int h=hash(st[s]);int u=head[h];while(u){if(memcmp(st[u],st[s],sizeof(st[0]))==0) return 0;u=next[u];}next[s]=head[h];head[h]=s;return 1;}int bfs(){memset(head,0,sizeof(head));int front=1,rear=2;while(front<rear){if(memcmp(goal,st[front],sizeof(st[0]))==0)return front;int z;for(z=0;z<9;z++)if(st[front][z]==0) break;int x=z/3,y=z%3;for(int d=0;d<4;d++){int newx=x+dx[d];int newy=y+dy[d];int newz=3*newx+newy;if(newx>=0&&newx<3&&newy>=0&&newy<3){memcpy(&st[rear],&st[front],sizeof(st[0]));st[rear][newz]=st[front][z];st[rear][z]=st[front][newz];dis[rear]=dis[front]+1;if(try_to_insert(rear)) rear++; }}front++;}return 0;}int main(int argc, char *argv[]){#ifdef WJ//freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#endiffor(int i=0;i<9;i++)scanf("%d",&st[1][i]);for(int i=0;i<9;i++)scanf("%d",&goal[i]);int ans=bfs();if(ans>0) printf("%d\n",dis[ans]);else printf("-1\n");return 0;}


0 0