洛谷P1379 八數碼難題 題解 A*搜尋
阿新 • • 發佈:2020-09-17
題目連結:https://www.luogu.com.cn/problem/P1379
一般搜尋:
#include <bits/stdc++.h> using namespace std; int tmp[3][3], dir[4][2] = { -1, 0, 1, 0, 0, -1, 0, 1 }; int parse(int s, int d) { for (int i = 0; i < 3; i ++) { for (int j = 0; j < 3; j ++) { tmp[i][j] = s % 10; s /= 10; } } int x, y; for (int i = 0; i < 3; i ++) for (int j = 0; j < 3; j ++) if (!tmp[i][j]) x = i, y = j; int xx = x + dir[d][0], yy = y + dir[d][1]; if (xx >= 0 && xx < 3 && yy >= 0 && yy < 3) { swap(tmp[x][y], tmp[xx][yy]); int res = 0, t = 1; for (int i = 0; i < 3; i ++) { for (int j = 0; j < 3; j ++) { res += tmp[i][j] * t; t *= 10; } } return res; } else return -1; } map<int, int> mp; int a; queue<int> que; int main() { cin >> a; if (a == 123804765) { puts("0"); return 0; } mp[a] = 0; que.push(a); while (!que.empty()) { int u = que.front(); que.pop(); int dis = mp[u]; for (int i = 0; i < 4; i ++) { int v = parse(u, i); if (v == -1 || mp.find(v) != mp.end()) continue; mp[v] = dis + 1; if (v == 123804765) { cout << dis + 1 << endl; return 0; } que.push(v); } } return 0; }
A星搜尋:
#include <bits/stdc++.h> using namespace std; const int target[3][3] = { 1, 2, 3, 8, 0, 4, 7, 6, 5 }; struct Matrix { int a[3][3]; int to_int() { int res = 0; for (int i = 0; i < 3; i ++) for (int j = 0; j < 3; j ++) res = res * 10 + a[i][j]; return res; } }; int h(Matrix a) { // 返回有多少個位置和終點不一樣 int cnt = 0; for (int i = 0; i < 3; i ++) for (int j = 0; j < 3; j ++) if (a.a[i][j] != target[i][j]) cnt ++; return cnt; } struct Node { Matrix a; // 當前格子的狀態 int step; // 一共走了多少步 bool operator < (Node b) const { return step + h(a) > b.step + h(b.a); } }; bool check(Node u) { for (int i = 0; i < 3; i ++) for (int j = 0; j < 3; j ++) if (u.a.a[i][j] != target[i][j]) return false; return true; } priority_queue<Node> que; char s[11]; int dir[4][2] = { -1, 0, 1, 0, 0, -1, 0, 1 }; set<int> st; int main() { scanf("%s", s); Node u; for (int i = 0; i < 3; i ++) for (int j = 0; j < 3; j ++) u.a.a[i][j] = s[i*3+j] - '0'; u.step = 0; que.push(u); while (!que.empty()) { Node u = que.top(); que.pop(); if (check(u)) { printf("%d\n", u.step); return 0; } int x, y; for (int i = 0; i < 3; i ++) for (int j = 0; j < 3; j ++) if (u.a.a[i][j] == 0) x = i, y = j; for (int i = 0; i < 4; i ++) { Node v = { u.a, u.step+1 }; int xx = x + dir[i][0], yy = y + dir[i][1]; if (xx >= 0 && xx < 3 && yy >= 0 && yy < 3) { swap(v.a.a[x][y], v.a.a[xx][yy]); int val = v.a.to_int(); if (st.count(val)) continue; st.insert(val); que.push(v); } } } puts("-1"); // 按照題目保證不會出現這種情況 return 0; }