题目链接
http://poj.org/problem?id=2286
分析
本题状态数太多,BFS不可行,题目保证有解,用IDA*算法。
每次操作最多会使中间八个格子中不是出现次数最多的数变成出现次数最多的数,可用来做估价函数。
记录上一次操作,此次不进行其逆操作。
AC代码
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
inline int read() {
int num = 0;
char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9')
num = num * 10 + c - '0', c = getchar();
return num;
}
const int maxn = 10;
int mx[maxn][maxn], d;
vector<char> ans;
inline int query() {
int cnt[4];
memset(cnt, 0, sizeof(cnt));
for (int i = 3; i <= 5; ++i)
for (int j = 3; j <= 5; ++j)
if (!(i == 4 && j == 4)) ++cnt[mx[i][j]];
if (cnt[1] > cnt[2]) swap(cnt[1], cnt[2]);
if (cnt[2] > cnt[3]) swap(cnt[2], cnt[3]);
return cnt[1] + cnt[2];
}
inline void change(int k) { // 注意移动元素的顺序问题
if (k == 0) {
mx[8][3] = mx[1][3];
for (int i = 1; i <= 7; ++i) mx[i][3] = mx[i + 1][3];
}
else if (k == 1) {
mx[8][5] = mx[1][5];
for (int i = 1; i <= 7; ++i) mx[i][5] = mx[i + 1][5];
}
else if (k == 2) {
mx[3][0] = mx[3][7];
for (int i = 7; i; --i) mx[3][i] = mx[3][i - 1];
}
else if (k == 3) {
mx[5][0] = mx[5][7];
for (int i = 7; i; --i) mx[5][i] = mx[5][i - 1];
}
else if (k == 4) {
mx[0][5] = mx[7][5];
for (int i = 7; i; --i) mx[i][5] = mx[i - 1][5];
}
else if (k == 5) {
mx[0][3] = mx[7][3];
for (int i = 7; i; --i) mx[i][3] = mx[i - 1][3];
}
else if (k == 6) {
mx[5][8] = mx[5][1];
for (int i = 1; i <= 7; ++i) mx[5][i] = mx[5][i + 1];
}
else {
mx[3][8] = mx[3][1];
for (int i = 1; i <= 7; ++i) mx[3][i] = mx[3][i + 1];
}
}
inline int dfs(int done, int op) {
int tot = query();
if (done + tot > d) return 0;
if (!tot) return 1;
int tmp[maxn][maxn];
memcpy(tmp, mx, sizeof(tmp));
for (int i = 0; i < 8; ++i) {
if ((op == 0 && i == 5) || (op == 5 && i == 0)) continue;
if ((op == 1 && i == 4) || (op == 4 && i == 1)) continue;
if ((op == 2 && i == 7) || (op == 7 && i == 2)) continue;
if ((op == 3 && i == 6) || (op == 6 && i == 3)) continue;
change(i);
ans.push_back(i + 'A');
if(dfs(done + 1, i)) return 1;
memcpy(mx, tmp, sizeof(mx));
ans.pop_back();
}
return 0;
}
int main() {
while (scanf("%d", &mx[1][3]) == 1 && mx[1][3]) {
mx[1][5] = read(), mx[2][3] = read(), mx[2][5] = read();
for (int i = 1; i <= 7; ++i) mx[3][i] = read();
mx[4][3] = read(), mx[4][5] = read();
for (int i = 1; i <= 7; ++i) mx[5][i] = read();
mx[6][3] = read(), mx[6][5] = read();
mx[7][3] = read(), mx[7][5] = read();
while (!ans.empty()) ans.pop_back();
d = 0;
while (!dfs(0, -1)) ++d;
if (!d) printf("No moves needed");
else for (int i = 0; i < (int)ans.size(); ++i) putchar(ans[i]);
printf("\n%d\n", mx[3][3]);
}
return 0;
}