题目描述
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
输入输出格式
输入格式:
输入初始状态,一行九个数字,空格用0表示
输出格式:
只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)
输入输出样例
输入样例#1:
复制
283104765
输出样例#1:
复制
4
思路:
1.双向广搜
1 #include <iostream> 2 #include <cstdio> 3 #include <queue> 4 #include <map> 5 #include <string> 6 #include <algorithm> 7 #define R register 8 using namespace std; 9 map<string,int> mp;int go[4][2]={{1,0},{-1,0},{0,1},{0,-1}};map<string,int> tmp; 10 struct tnode 11 { 12 int step;string s;int ox,oy; 13 };tnode start,end; 14 inline int A(string t) 15 { 16 string s="123804765"; 17 int sum=0; 18 for(R int i=0;i<9;i++) 19 if(t[i]^s[i]) sum++; 20 return sum; 21 } 22 inline int tA(string t) 23 { 24 string s=start.s; 25 int sum=0; 26 for(R int i=0;i<9;i++) 27 if(t[i]^s[i]) sum++; 28 return sum; 29 } 30 inline void bfs() 31 { 32 queue<tnode> q; 33 q.push(start); 34 queue<tnode> p; 35 p.push(end); 36 if(start.s==end.s) 37 { 38 cout<<0<<endl; 39 return ; 40 } 41 while(!q.empty()&&!p.empty()) 42 { 43 if(q.size()<p.size()) 44 { 45 tnode now=q.front();q.pop(); 46 if(tmp[now.s]^0) 47 { 48 cout<<now.step+tmp[now.s]<<endl; 49 return; 50 } 51 for(int i=0;i<4;i++) 52 { 53 tnode t=now; 54 t.ox=now.ox+go[i][0]; 55 t.oy=now.oy+go[i][1]; 56 if(t.ox<1||t.oy<1||t.ox>3||t.oy>3) continue; 57 swap(t.s[(t.ox-1)*3+t.oy-1],t.s[(now.ox-1)*3+now.oy-1]); 58 if(mp[t.s]==0&&A(t.s)-2<=A(now.s)) 59 { 60 mp[t.s]=t.step+1; 61 t.step++; 62 q.push(t); 63 } 64 } 65 } 66 else 67 { 68 tnode now=p.front();p.pop(); 69 if(mp[now.s]^0) 70 { 71 cout<<now.step+mp[now.s]<<endl; 72 return; 73 } 74 for(int i=0;i<4;i++) 75 { 76 tnode t=now; 77 t.ox=now.ox+go[i][0]; 78 t.oy=now.oy+go[i][1]; 79 if(t.ox<1||t.oy<1||t.ox>3||t.oy>3) continue; 80 swap(t.s[(t.ox-1)*3+t.oy-1],t.s[(now.ox-1)*3+now.oy-1]); 81 if(tmp[t.s]==0&&tA(t.s)-2<=tA(now.s)) 82 { 83 tmp[t.s]=t.step+1; 84 t.step++; 85 p.push(t); 86 } 87 } 88 } 89 } 90 } 91 int main() 92 { 93 //freopen("a.in","r",stdin); 94 //freopen("a.out","w",stdout); 95 start.step=end.step=0; 96 cin>>start.s;end.s="123804765"; 97 mp[start.s]=1;tmp[end.s]=1; 98 for(int i=0;i<start.s.size();i++) 99 if(start.s[i]=='0') 100 { 101 start.ox=i/3+1; 102 start.oy=i%3+1; 103 break; 104 } 105 end.ox=2;end.oy=2; 106 bfs(); 107 return 0; 108 }
迭代加深:
1 // luogu-judger-enable-o2 2 #include <iostream> 3 #include <map> 4 #include <algorithm> 5 #include <string> 6 #include <cstdio> 7 #define R register 8 using namespace std; 9 int a[4][4];int ans=100000; 10 int go[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; 11 map<int,bool> mp;int f=0;int k=-1; 12 int b[4][4]; 13 inline int A() 14 { 15 R int sum=0; 16 for(R int i=1;i<=3;i++) 17 for(R int j=1;j<=3;j++) 18 if(b[i][j]!=a[i][j]) sum++; 19 return sum; 20 } 21 inline bool ok() 22 { 23 for(R int i=1;i<=3;i++) 24 for(R int j=1;j<=3;j++) 25 if(b[i][j]!=a[i][j]) return 0; 26 return 1; 27 } 28 inline void dfs(int x,int y,int step) 29 { 30 if(f) return; 31 if(ok()){f=1;return;} 32 if(step>=k) return; 33 for(R int i=0;i<4;i++) 34 { 35 R int nx=x+go[i][0],ny=y+go[i][1]; 36 if(nx<1||ny<1||nx>3||ny>3) continue; 37 38 swap(a[x][y],a[nx][ny]); 39 R int pd=0; 40 for(R int h=1;h<=3;h++) for(R int l=1;l<=3;l++) pd=pd*10+a[h][l]; 41 if(mp[pd]==0) if(step+A()<=k) { 42 mp[pd]=1,dfs(nx,ny,step+1),mp[pd]=0;/*cout<<pd<<endl;*/} 43 swap(a[x][y],a[nx][ny]); 44 } 45 } 46 int main() 47 { 48 //freopen("a.in","r",stdin); 49 //freopen("a.out","w",stdout); 50 b[1][1]=1;b[1][2]=2;b[1][3]=3;b[2][1]=8;b[2][2]=0;b[2][3]=4;b[3][1]=7;b[3][2]=6;b[3][3]=5; 51 R int x,y;R int pd=0; 52 for(R int i=1;i<=3;i++) 53 for(R int j=1;j<=3;j++) 54 { 55 char c; 56 cin>>c; 57 a[i][j]=c^48; 58 if(a[i][j]==0) x=i,y=j; 59 pd=(pd<<1)+(pd<<3)+a[i][j]; 60 } 61 mp[pd]=1; 62 while(!f) 63 k++,dfs(x,y,0); 64 cout<<k<<endl; 65 return 0; 66 }