本来认为是个数学题或者dp题,但是后来看到规则发现用搜索完全可以做
因为规则限制,每次只能把空白左边下一位的数移动到空白处,所以每次最多走4种情况,这就可以bfs了
一开始用map的,但是TLE了(虽然不是这个问题)于是手写hash,对999991取了个余,虽然一定不完善,但是数据没那么强。
手写hash后依旧TLE……最后检查了好几遍才发现是空格左边可能仍是空格,这一点没有考虑到,所以一直TLE(差点手写队列了o(╯□╰)o)
加了个判断后,500ms就过了……
注意位运算的优先级,今天被坑好几次了
/*
author:jxy
lang:C/C++
university:China,Xidian University
**If you need to reprint,please indicate the source**
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <map>
#define INF 1E9
using namespace std;
const char ss[32]={11,12,13,14,15,16,17,0,21,22,23,24,25,26,27,0,31,32,33,34,35,36,37,0,41,42,43,44,45,46,47,0};
string aim="";
struct node
{
int x,y;
};
char m[4][8];
struct state
{
node pos[50],blank[4];//pos确定每个数字位置,blank是4个空格位置
string s;//图
int lvl;//步数
};
string m2s()//把图变成字符串
{
string now="";
int i,j;
for(i=0;i<4;i++)
for(j=0;j<8;j++)
now.push_back(m[i][j]);
return now;
}
int get_hash(string s)//获得hash值
{
long long ans=0;
for(int i=0;i<32;i++)
ans=(ans<<1)+s[i];
return ans%999991;
}
bool vis[1000000];
queue<state> q;
state now,next;
node temp;
int bfs()
{
memset(vis,0,sizeof(vis));
while(!q.empty())q.pop();
int i,j,t=0,k,o,lvl;
for(i=0;i<4;i++)
for(j=0;j<8;j++)
{
temp.x=i;temp.y=j;
if(m[i][j]==0)now.blank[t++]=temp;
else now.pos[m[i][j]]=temp;
}
now.s=m2s();vis[get_hash(now.s)]=1;
now.lvl=1;
q.push(now);
int Aim=get_hash(aim);
while(!q.empty()&&!vis[Aim])
{
now=q.front();q.pop();
next=now;
next.lvl=now.lvl+1;
for(i=0;i<4;i++)
{
node &b=next.blank[i];
o=8*b.x+b.y-1;
t=next.s[o];
if(t%10==7||t==0)continue;//注意空格旁还是空格的情况
k=t+1;
node &p=next.pos[k];
k=p.x*8+p.y;
o++;
swap(next.s[o],next.s[k]);//移动位置
t=get_hash(next.s);
if(!vis[t])
{
if(t==Aim)return next.lvl-1;
swap(p,b);
q.push(next);
vis[t]=1;
swap(p,b);
}
swap(next.s[o],next.s[k]);//恢复
}
}
return vis[Aim]-1;
}
int main()
{
int T;
for(T=0;T<32;T++)aim.push_back(ss[T]);
scanf("%d",&T);
while(T--)
{
memset(m,0,sizeof(m));
int i,j,t;
for(i=0;i<4;i++)
for(j=1;j<8;j++)
{
scanf("%d",&t);
m[i][j]=(char)t;
if(t%10==1) swap(m[i][j],m[(t/10)-1][0]);
}
printf("%d\n",bfs());
}
}