问题与程序参考《挑战程序设计竞赛》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