acwing-195. 骑士精神

考点

  • 双向BFS
  • IDAstar

题解

见思路

思路

每次其实移动的是空白格,不是棋子

IDAstar

题目告诉你最多15步,考虑IDAstar

由于每次最多把一个棋子移到合适的地方,所以估价函数就等于当前未到目标位置棋子的数量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5;
const int dx[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
const int dy[8] = {1, 2, 2, 1, -1, -2, -2, -1};
const char ans[maxn][maxn + 1] = {"11111", "01111", "00*11", "00001", "00000"};
char g[maxn][maxn];

int f() {
int res = 0;
for (int i = 0; i < 5; ++i) {
for (int j = 0; j < 5; ++j) {
if (g[i][j] != '*' && g[i][j] != ans[i][j]) ++res;
}
}
return res;
}

bool ida(int x, int y, int depth, int mxdepth) {
if (depth + f() > mxdepth) return false;
if (!f()) return true;
for (int i = 0; i < 8; ++i) {
int nx = x + dx[i], ny = y + dy[i];
if (nx < 0 || ny < 0 || nx > 4 || ny > 4) continue;
swap(g[x][y], g[nx][ny]);
if (ida(nx, ny, depth + 1, mxdepth)) return true;
swap(g[x][y], g[nx][ny]);
}
return false;
}

int main() {
int t, x, y;
cin >> t;
while (t--) {
for (int i = 0; i < 5; ++i) {
for (int j = 0; j < 5; ++j) {
cin >> g[i][j];
if (g[i][j] == '*') x = i, y = j;
}
}
int depth = 0;
while (depth < 16 && !ida(x, y, 0, depth)) ++depth;
cout << (depth < 16 ? depth : -1) << endl;
}
return 0;
}

双向BFS

由于已知起始状态和目标状态,且没有什么有效剪枝,可以考虑双向BFS,直接套模板即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <bits/stdc++.h>
using namespace std;
const int dx[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
const int dy[8] = {1, 2, 2, 1, -1, -2, -2, -1};
string a, b = "1111101111002110000100000";

struct node {
string state_;
int x_, y_, step_;
node(string state = "", int x = 0, int y = 0, int step = 0)
: state_(state), x_(x), y_(y), step_(step) {}
};

bool valid(int x, int y) { return x >= 0 && y >= 0 && x < 5 && y < 5; }

int extend(queue<node> &aq, queue<node> &bq, unordered_map<string, bool> &av,
unordered_map<string, bool> &bv) {
int sz = aq.size();
while (sz--) {
string s = aq.front().state_;
int x = aq.front().x_, y = aq.front().y_, step = aq.front().step_;
aq.pop();
for (int i = 0; i < 8; ++i) {
int nx = x + dx[i], ny = y + dy[i];
if (!valid(nx, ny)) continue;
string ns = s;
swap(ns[x * 5 + y], ns[nx * 5 + ny]);
if (av.count(ns)) continue;
if (bv.count(ns)) return bq.front().step_ + step + 1;
av[ns] = 1;
aq.emplace(ns, nx, ny, step + 1);
}
}
return -1;
}

int bfs(int ax, int ay) {
unordered_map<string, bool> av, bv;
queue<node> aq, bq;
if (a == b) return 0;
av[a] = 1, bv[b] = 1;
aq.push({a, ax, ay, 0}), bq.push({b, 2, 2, 0});
int res = 0, cnt = 1;
while (aq.size() && bq.size()) {
if (aq.size() < bq.size()) {
res = extend(aq, bq, av, bv);
} else {
res = extend(bq, aq, bv, av);
}
if (~res) return res;
if (++cnt > 15) break;
}
return -1;
}

int main() {
int t, x, y, res;
char c;
cin >> t;
while (t--) {
a = "";
for (int i = 0; i < 5; ++i) {
for (int j = 0; j < 5; ++j) {
cin >> c;
if (c == '*') c = '2', x = i, y = j;
a += c;
}
}
res = bfs(x, y);
cout << res << endl;
}
return 0;
}