题目
简化题意
给你一个八数码,问你最少几步可以移动到目标状态。类似下图。
思路
双向宽搜。
挺暴力的,感觉没啥需要讲的。
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 << '
';
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
", 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;
}