题目大意 :
给出初始的积木样子 :
0
1 1
2 2 2
3 3 3 3
4 4 4 4 4
5 5 5 5 5 5
现将打乱,每次可将 0 和左上,上,下,右下的交换,求最小步数, 超过20, 输出 233。
输入简述 :
输入 T , 表示数据,每组为打乱积木图。
输出简述 :
T 个答案。
sample intput :
1
1
2 0
2 1 2
3 3 3 3
4 4 4 4 4
5 5 5 5 5 5
sample output :
3
题解 :
这道题一看很板啊, A*套上就过了, 但是考后和别人聊了一下才发现我的是假的 A *, 因为我的是DFS,正版的是 BFS,后来想想也是, 难怪我的跑的那么慢。
预估函数 : 当前步数 + 期望最小步数 < 20 , 最小步数位当前不匹配数。
代码 :
DFS 的 A*
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <ctime>
#include <map>
#include <vector>
#define LL long long
using namespace std;
inline int read() {
int i = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {
if(ch == '-') f = -1; ch = getchar();
}
while(ch >= '0' && ch <= '9') {
i = (i << 3) + (i << 1) + ch - '0'; ch = getchar();
}
return i * f;
}
const int mod = 981256453;
int sta[7][7] = {
{0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0},
{0, 1, 1, 0, 0, 0, 0},
{0, 2, 2, 2, 0, 0, 0},
{0, 3, 3, 3, 3, 0, 0},
{0, 4, 4, 4, 4, 4, 0},
{0, 5, 5, 5, 5, 5, 5},
};
int a[7][7], ans, x[4] = {-1, -1, 1, 1}, y[4] = {-1, 0, 0, 1};
int zx, zy, vis[7][7], f[7][7], pow1[30], hao[7][7], tail;
map<LL, int> b;
map<int, LL> c;
inline int judge() {
int now = 0;
memset(f, 0, sizeof(f));
for(int i = 1; i <= 6; ++i)
for(int j = 1; j <= i; ++j)
if(a[i][j] != sta[i][j])
++now, f[i][j] = 1;
return now;
}
inline void print() {
for(int i = 1; i <= 6; ++i) {
for(int j = 1; j <= i; ++j)
printf("%d ", a[i][j]);
printf("\n");
}
}
inline LL solve() {
LL now = 0;
for(int i = 1; i <= 6; ++i)
for(int j = 1; j <= i; ++j)
now = (now + (LL)a[i][j] * pow1[hao[i][j]] % mod) % mod;
return now;
}
inline void dfs(int now, int lx, int ly) {
int num = judge();
if(!num) { ans = min(ans, now); return; }
if(num + now > 20) return ;
LL g = solve();
if(!b[g]) b[g] = now + 1, c[++tail] = g;
else if(b[g] > now + 1) b[g] = now + 1;
else return ;
for(int i = 0; i < 4; ++i) {
int nx = lx + x[i], ny = ly + y[i];
if(vis[nx][ny]) {
swap(a[nx][ny], a[lx][ly]);
dfs(now + 1, nx, ny);
swap(a[nx][ny], a[lx][ly]);
}
}
}
inline void init() {
int cnt = -1;
for(int i = 1; i <= 6; ++i)
for(int j = 1; j <= i; ++j)
vis[i][j] = 1, hao[i][j] = ++cnt;
pow1[0] = 1;
for(int i = 1; i <= 20; ++i) pow1[i] = pow1[i - 1] * 7 % mod;
}
int main() {
int times = read();
init();
while(times--) {
for(int i = 1; i <= tail; ++i) b[c[i]] = 0; tail = 0;
for(int i = 1; i <= 6; ++i)
for(int j = 1; j <= i; ++j) {
a[i][j] = read();
if(!a[i][j]) zx = i, zy = j;
}
ans = 0x3f3f3f3f;
dfs(0, zx, zy);
if(ans != 0x3f3f3f3f) printf("%d\n", ans);
else printf("233\n");
}
}