问题与程序参考《挑战程序设计竞赛》19.2 ALDS1_13_B:8 Puzzle

1 /*
2 3*3拼图用的是广度优先搜索
3 编程核心关键词是这么几个
4 队列queue 拼图数据结构puzzle 状态记录数组V 方向数组dx,dy 、
5 开始会看这算法,可能会被吓着,觉得好难,但实际上理解一番,、
6 就会发现这个算法实际上就是模拟我们拼图,但与我们拼图不太一样的
7 是:
8 1.它会记住所有自己试探的失败情况(状态记录数组V);
9 2.它会按照“规则”一个个来试探,而不像我们人一样,按照自己的感觉与大致推断来进行试探;
10 [当然,这种人具有的感觉性的“预判”也是能在算法里量化大概模拟下的,也就是进行“剪枝”操作,
11 涉及IDA*(迭代加深A*)、A*]
12
13 编程方面的话,开始时候创建一个自定义数据类型Puzzle,里面包含
14 f[N2] 对应某阶段的拼图
15 space 空格所处位置的下标
16 path 记录移动的方法
17 以及<的运算符重载
18
19 利用广度优先搜索,弹出队列首部的Puzzle,
20 在预先的“是否找寻到最终目标”的judge函数判断后开始进行"试探”,
21 利用Puzzle.space与行下标x,列下标y的对应关系,
22 x=u.space/3; //行下标
23 y=u.space%3; //列下标
24 生成空白块的在二维数组f的位置信息
25 随后,利用for循环、dx、dy、空白块位置,进行"符合规则”的试探,
26 并将新生成的Puzzle放入队列queue之中
27 在经过多次试探后,如果有答案,会输出答案,但如果没有答案,即
28 "队列为空",就输出“unsolvable”
29
30 博客里放了张图,这是为了更快理清"输入样例1"的处理过程而画的
31 */
32 #include<iostream>
33 #include<cmath>
34 #include<string>
35 #include<map>
36 #include<queue>
37 using namespace std;
38 #define N 3
39 #define N2 9
40 static const int dx[4]={-1,0,1,0};
41 static const int dy[4]={0,-1,0,1};
42 static const char dir[4]={'u','l','d','r'};
43 struct Puzzle{
44 int f[N2];
45 int space;
46 string path;
47 bool operator < (const Puzzle &p)const{
48 for(int i=0;i<N2;i++){
49 if(f[i]==p.f[i]) continue;
50 return f[i]>p.f[i];
51 }
52 return false;
53 }
54 };
55 bool judge(Puzzle p){
56 for(int i=0;i<N2;i++){
57 if(p.f[i]!=(i+1))
58 return false;
59 }
60 return true;
61 }
62 void showpic(Puzzle s){
63 cout<<"path:"<<s.path;
64 for(int i=0;i<N2;i++){
65 if(!(i%3)) cout<<endl;
66 if(s.f[i]!=9)
67 cout<<s.f[i]<<" ";
68 else
69 cout<<"0 ";
70 }
71 cout<<endl;
72 }
73 string bfs(Puzzle s){
74 queue<Puzzle> Q;
75 map<Puzzle,bool> V;//记录是否已经使用过
76 Puzzle u,v;
77 s.path="";//空白字符串
78 Q.push(s);//入队列
79 V[s]=true;
80 while(!Q.empty()){
81 u=Q.front();
82 Q.pop();
83 //showpic(u);//显示当前移动情况
84 if(judge(u)) return u.path;
85 int sx=u.space/N;
86 int sy=u.space%N;
87 for(int r=0;r<4;r++){
88 int tx=sx+dx[r];
89 int ty=sy+dy[r];
90 if(tx<0||ty<0||tx>=N||ty>=N) continue;
91 v=u;
92 swap(v.f[u.space],v.f[tx*N+ty]);
93 v.space=tx*N+ty;
94 if(!V[v]){
95
96 V[v]=true;//访问标记
97 v.path+=dir[r];
98 Q.push(v);
99 }
100 }
101
102 }
103
104 return "unsolvable";
105
106 }
107 int main(){
108 Puzzle in;
109 for(int i=0;i<N2;i ++){
110 cin>>in.f[i];
111 if(in.f[i]==0){
112 in.f[i]=N2;
113 in.space=i;
114 }
115 }
116 string ans=bfs(in);
117 cout<<"answer:"<<ans<<endl;
118 cout<<ans.size()<<endl;//最终的结果
119 }
120 /*样例输入1
121 1 3 0
122 4 2 5
123 7 8 6
124 样例输出1
125 answer:ldrd
126 4
127 */
128 /*样例输入2
129 1 2 3
130 4 5 6
131 8 7 0
132 样例输出2
133 answer:unsolvable
134 10
135 */
136
来源:https://www.cnblogs.com/memocean/p/12263069.html