洛谷P1379 八数码难题 题解 A*搜索
题目链接: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;
}