八数码问题是一个经典的人工智能问题。具体问题不累述了。
思路:由于存在多组测试数据,可以考虑“打表法“。所谓打表法,即枚举所有的初始情况,记录其到达终点的路径。而在这个题目中,顺序打表会调用很多次BFS,所以我们采用逆序打表,只要调用一次BFS。
代码如下:
1 /*************map存路径,set判重,string存状态*****************/ 2 /*********************暴力广搜 + STL **************************/ 3 #include<stdio.h> 4 #include<iostream> 5 #include<queue> 6 #include<map> 7 #include<set> 8 #include<algorithm> 9 #include<sstream> 10 using namespace std; 11 map<string, string>slu; 12 set<string>visited; 13 int dir[4][2] = { {-1,0},{1,0},{0,1},{0,-1} }; 14 string base = "udrl"; 15 char input[1000]; 16 struct node { 17 string sta; 18 string path; 19 int pos; //x所在的位置 20 node(string stas, string paths, int poss) { 21 sta = stas; 22 path = paths; 23 pos = poss; 24 } 25 }; 26 bool check(int x, int y) 27 { 28 if (x >= 0 && x < 3 && y >= 0 && y < 3) 29 return true; 30 else 31 return false; 32 } 33 void prv_bfs() 34 { 35 queue<node>q; 36 set<string>v; 37 q.push(node("12345678x", "", 8)); //从目标状态往回扩展 38 slu["12345678x"] = " "; 39 v.insert("12345678X"); 40 while (!q.empty()) 41 { 42 struct node h = q.front(); 43 q.pop(); 44 45 int a = h.pos / 3; 46 int b = h.pos % 3; //得到x的坐标 47 for (int i = 0; i < 4; i++) 48 { 49 int x = a + dir[i][0]; 50 int y = b + dir[i][1]; 51 int pos = 3 * x + y; 52 if (!check(x, y)) 53 continue; 54 swap(h.sta[h.pos], h.sta[pos]); 55 if (slu.find(h.sta) != slu.end()) 56 { 57 swap(h.sta[h.pos], h.sta[pos]); 58 continue; 59 } 60 q.push(node(h.sta, h.path + base[i], pos)); 61 slu[h.sta] = h.path + base[i]; 62 v.insert(h.sta); 63 swap(h.sta[h.pos], h.sta[pos]); 64 } 65 } 66 } 67 int main() 68 { 69 prv_bfs(); 70 while (~scanf("%s", input)) 71 { 72 string line = ""; 73 line = line + input[0]; 74 for (int i = 1; i <= 8; i++) 75 { 76 scanf("%s", input); 77 line = line + input[0]; 78 } 79 if (slu[line] == "") cout << "unsolvable" << endl; 80 else cout << slu[line] << endl; 81 } 82 83 return 0; 84 85 }
当然,这一题还有很多很好的方法,我会慢慢补充。
新手入门,希望多多交流!