在一个 的方框内摆放了若干个相同的玩具,要将这些玩具重新摆放成为理想的状态,规定移动时只能将玩具向上下左右四个方向移动,并且移动到的位置不能有玩具,求最小移动次数。
链接
题解
将所有 个方框的状态存入一个整数的二进制位中,BFS 即可。
代码
#include <cstdio>
#include <climits>
#include <queue>
const int MAXN = 16;
inline unsigned int read() {
unsigned int res = 0;
for (int i = 0; i < 4; i++) {
char s[4 + 1];
scanf("%s", s);
for (int j = 0; j < 4; j++) {
if (s[j] == '1') res |= (1 << (4 * i + j));
}
}
return res;
}
inline int bfs(unsigned int s, unsigned int t) {
static int dist[1 << MAXN];
for (int i = 0; i < (1 << MAXN); i++) dist[i] = INT_MAX;
std::queue<unsigned int> q;
dist[s] = 0;
q.push(s);
while (!q.empty()) {
unsigned int v = q.front();
q.pop();
if (v == t) return dist[v];
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
int a = 4 * i + j;
unsigned int va = !!(v & (1 << a));
if (i != 3) {
int b = 4 * (i + 1) + j;
unsigned int vb = !!(v & (1 << b));
if (va != vb) {
unsigned int u = v;
if (vb) u |= (1 << a);
else u &= ~(1 << a);
if (va) u |= (1 << b);
else u &= ~(1 << b);
if (dist[u] > dist[v] + 1) {
dist[u] = dist[v] + 1;
q.push(u);
}
}
}
if (j != 3) {
int b = 4 * i + (j + 1);
unsigned int vb = !!(v & (1 << b));
if (va != vb) {
unsigned int u = v;
if (vb) u |= (1 << a);
else u &= ~(1 << a);
if (va) u |= (1 << b);
else u &= ~(1 << b);
if (dist[u] > dist[v] + 1) {
dist[u] = dist[v] + 1;
q.push(u);
}
}
}
}
}
}
return -1;
}
int main() {
unsigned int s = read(), t = read();
printf("%d\n", bfs(s, t));
return 0;
}