拼圖問題
在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;
}