题目: LINK
如果对于每个数据,直接搜索5步内能否到达终态,会TLE。
其实,可以发现终态是固定的,就是2*4!种。所以可以从终态开始搜索。
1111
2222
3333
4444
和
1234
1234
1234
1234
以这两个为初始状态搜索,相当于预处理。之后对于每个输入的数据可以进行映射,其实就是4!种的排列。对于每一种映射,取步数最少的就可以了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<cmath>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define INF 1000000000
#define N 100111
typedef __int64 LL;
struct node
{
LL num;
int step;
};
node S;
struct no
{
int mat[9][9];
};//
int vis[10], match[10], ans;
map<LL, int> mm;
no t, ret, xx;
LL change(LL x, int id)
{
for(int i = 4; i>=1; i--) {
for(int j = 4; j >= 1; j--){
t.mat[i][j] = x % 4; x /= 4;
}
}
ret = t;
if(id<=4) {
for(int i = 1; i<=3; i++) ret.mat[id][i] = t.mat[id][i+1];
ret.mat[id][4] = t.mat[id][1];
}
else if(id <= 8) {
id = id - 4;
for(int i = 4; i>=2; i--) ret.mat[id][i] = t.mat[id][i-1];
ret.mat[id][1] = t.mat[id][4];
}
else if(id <=12) {
id = id - 8;
for(int i = 1; i <= 3; i++) ret.mat[i][id] = t.mat[i+1][id];
ret.mat[4][id] = t.mat[1][id];
}
else if(id <=16) {
id = id - 12;
for(int i = 4; i>=2; i--) ret.mat[i][id] = t.mat[i-1][id];
ret.mat[1][id] = t.mat[4][id];
}
LL rr = 0;
for(int i = 1; i <= 4; i++) {
for(int j = 1; j <= 4; j++) rr *= 4, rr += ret.mat[i][j];
}
return rr;
}
void bfs()
{
S.step = 1;
queue<node > Q;
Q.push(S);
mm[S.num] = 1;
node now, next;
while(!Q.empty()) {
now = Q.front(); Q.pop();
if(now.step > 6) continue;
for(int i = 1; i <= 16; i++) {//进行 16种变换
next.num = change(now.num, i);
next.step = now.step + 1;
if(next.step > 6) continue;
if(mm[next.num] == 0) mm[next.num] = INF;
if(mm[next.num] > next.step) {
mm[next.num] = next.step;
Q.push(next);
}
}
}
}
void dfs(int id)
{
if(id > 3) {
LL tmp = 0;
for(int i = 1; i <= 4; i++) {
for(int j = 1; j <= 4; j++) {
LL tt = match[xx.mat[i][j]];
tmp *= 4; tmp += tt;
}
}
int flag = mm[tmp] ;
if(flag == 0) return ;
ans = min(ans, flag);
return ;
}
for(int i = 0 ; i <= 3; i++) {
if(vis[i]) continue;
match[id] = i; vis[i] = 1;
dfs(id + 1);
vis[i] = 0;
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif // ONLINE_JUDGE
S.num = 0;
for(int i = 1; i <= 4; i++) {
for(int j = 1; j <= 4; j++) {
S.num *= 4; S.num += i-1;
}
}
bfs();
S.num = 0;
for(int i = 1; i <= 4; i++) {
for(int j = 1; j <= 4; j++) {
S.num *= 4; S.num += j-1;
}
}
bfs();
int t;
scanf("%d",&t);
while( t -- ) {
for(int i = 1; i<=4; i++) {
for(int j = 1; j <= 4 ; j++) {
scanf("%I64d", &xx.mat[i][j]);
xx.mat[i][j] -- ;
}
}
ans = INF;
memset(vis, 0, sizeof(vis));
dfs(0);
if(ans >= INF) puts("-1");
else printf("%d\n", ans-1);
}
return 0;
}