「題解」洛谷 P1379 八數碼難題
阿新 • • 發佈:2020-08-29
題目
簡化題意
給你一個八數碼,問你最少幾步可以移動到目標狀態。類似下圖。
思路
雙向寬搜。
挺暴力的,感覺沒啥需要講的。
Code
#include <cstdio> #include <cstring> #include <string> #include <iostream> #include <algorithm> #include <queue> #include <map> int p[10][5], cnt[10]; char s[10], t[10]; bool flag; struct Node { char a[10]; }; std::queue<Node> q[2]; std::map<std::string, bool> m[2]; int find0(Node x) { for (int i = 1; i <= 9; ++i) { if (x.a[i] == '0') return i; } } void okay(Node x, int typ) { std::string bz = ""; for (int i = 1; i <= 9; ++i) { bz += x.a[i]; } if (!m[typ][bz]) { //std::cout << bz << '\n'; m[typ][bz] = true; q[typ].push(x); } } void work(int typ) { int size = q[typ].size(); while (size--) { Node u = q[typ].front(); q[typ].pop(); std::string bz = ""; for (int i = 1; i <= 9; ++i) { bz += u.a[i]; } if (m[typ ^ 1][bz] == true) { flag = 1; return; } int pos = find0(u); for (int i = 1; i <= cnt[pos]; ++i) { std::swap(u.a[pos], u.a[p[pos][i]]); okay(u, typ); std::swap(u.a[pos], u.a[p[pos][i]]); } } } void bfs() { int cnt = 0; Node c, d; std::string e = "", f = ""; for (int i = 1; i <= 9; ++i) { c.a[i] = s[i]; d.a[i] = t[i]; e += s[i]; f += t[i]; } q[0].push(c), q[1].push(d); m[0][e] = 1, m[1][f] = 1; while (1) { ++cnt; //puts("qwq"); if (q[0].size() < q[1].size()) work(0); else work(1); if (flag == true) { printf("%d\n", cnt - 1); return; } } } int main() { std::cin >> s + 1; t[1] = '1', t[2] = '2', t[3] = '3'; t[4] = '8', t[5] = '0', t[6] = '4'; t[7] = '7', t[8] = '6', t[9] = '5'; cnt[1] = 2, cnt[2] = 3, cnt[3] = 2; cnt[4] = 3, cnt[5] = 4, cnt[6] = 3; cnt[7] = 2, cnt[8] = 3, cnt[9] = 2; p[1][1] = 2, p[1][2] = 4; p[2][1] = 1, p[2][2] = 3, p[2][3] = 5; p[3][1] = 2, p[3][2] = 6; p[4][1] = 1, p[4][2] = 5, p[4][3] = 7; p[5][1] = 2, p[5][2] = 4, p[5][3] = 6, p[5][4] = 8; p[6][1] = 3, p[6][2] = 5, p[6][3] = 9; p[7][1] = 4, p[7][2] = 8; p[8][1] = 5, p[8][2] = 7, p[8][3] = 9; p[9][1] = 6, p[9][2] = 8; bfs(); return 0; }