八数码

题目描述

在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 } 

 

 

转载于:https://www.cnblogs.com/000226wrp/p/10970527.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值