拼图问题
在3*3的拼图中,如何用最少步骤拼好它,这个问题是一个最短路径问题,可以使用BFS来求解,每个节点是一个状态,然后得到最少步骤,中间状态可能需要对每一个状态进行编码或者散列记录才能输出,本代码只解决了求最短步数,其实利用一个栈是可以实现打印解题过程的。
代码
#include<bits/stdc++.h>
using namespace std;
typedef int State[9];
const int maxstate=1000000;
State st[maxstate],goal;
int dist[maxstate];
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
int vis[362880],fact[9];
void init_lookup_table(){
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_lookup_table();
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(){
freopen("F://inp.txt","r",stdin);
for(int i=0;i<9;i++) cin>>st[1][i];
for(int i=0;i<9;i++) cin>>goal[i];
for(int i=0;i<9;i++){if(i&&i%3==0) cout<<endl;cout<<st[1][i]<<" ";}
int ans=bfs();
if(ans>0) printf("\nNeed %d steps come out!\n",dist[ans]);
else printf("\nNo way!\n");
for(int i=0;i<9;i++){if(i&&i%3==0) cout<<endl;cout<<goal[i]<<" ";}
return 0;
}