Aizu/Aoj 0121 Seven Puzzle

  

  这题应该算是经典的八数码问题的弱化版吧:给你一个4x2的方版,上面有0-7 八个数字,每次只能让编号0的方格跟他的上下左右的方格交换;所以也就是把方格0当做空格看待,每次只有空格周围的方格能够向空格处移动。   然后问从输入的方格样式变换到字典序最小的"01234567" 最少需要多少次。 

  解法是用bfs 求最少次数(跟求最短路径方式类似)。   我这里用的是打表的方法:对于方格的状态,我是用string来存的,下标0-7分别表示从左到右,从上到下的方格上的数字。  一开始队列中只放入"01234567"的状态; 然后从它开始进行bfs,  用个map<string,int> 来存放已得到的状态和需要的步数;  同时 这个map也是用来判重的。   而方格0的移动的话,  每次只有上下左右,因为是用字符串存状态的,所以对应上下左右 其字符所在下标的变换就是{-4,+4,-1,+1};    注意变换后下标是否在0-7范围内以及0原始位置是在左下角和右上角的特殊情况。  

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <cmath>
 6 #include <cstdlib>
 7 #include <cctype>
 8 #include <queue>
 9 #include <stack>
10 #include <map>
11 #include <vector>
12 #include <set>
13 #include <utility>
14 #define ll long long
15 #define inf 0x3f3f3f3f
16 using namespace std;
17 
18 typedef pair<string,int> P;
19 string str;
20 map<string,int> table;
21 int dir[]= {-1,1,-4,4}; //移动方向
22 void bfs()
23 {
24     queue<P> q;
25     string s,s_next;
26     P temp;
27     int cur,next;
28     q.push(P("01234567",0));
29     table["01234567"]=0;
30     while(!q.empty())
31     {
32         temp=q.front();
33         q.pop();
34         s=temp.first;
35         cur=temp.second;
36         for(int i=0; i<4; i++)//将0向四个方向移动
37         {
38             next=cur+dir[i];
39             str=s;
40             swap(str[cur],str[next]);
41             if(next>=0&&next<8&&!(cur==3&&next==4)&&!(cur==4&&next==3)&&table.find(str)==table.end())
42             {                           //判断移动是否合法及该状态是否已存在
43                 table[str]=table[s]+1;
44                 q.push(P(str,next));
45             }
46         }
47     }
48 }
49 int main()
50 {
51     //freopen("input.txt","r",stdin);
52     char sstr[50];
53     bfs();
54     while(gets(sstr))
55     {
56         for(int i=1; i<8; i++)
57             sstr[i]=sstr[i*2];
58         sstr[8]='';
59         str=sstr;
60         printf("%d
",table[str]);
61     }
62 }
原文地址:https://www.cnblogs.com/geek1116/p/5672991.html