Description
给出一个六层的地图,从上到下第 i i 层有个块,以 (i,j) ( i , j ) 表示第 i+1 i + 1 层从左到右第 j+1 j + 1 个块的坐标,一个块可以和与其相邻的块交换,两个块相邻当且仅当其某维坐标相同,第 i i 层块编号均为,现在给出一个地图初始状态,要把编号为 0 0 的块移动到处,问最少步数
Input
第一行一整数 T T 表示用例组数,每组用例输入一个地图的初始状态
Output
如果可以在以内把 0 0 移动到处则输出最少步数,否则输出 "too difficult" " t o o d i f f i c u l t "
Sample Input
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
Solution
每块编号为 0 0 ~,共 21 21 个块,按六进制把整个地图 Hash H a s h 得到地图的状态,然后从起点和终点开始双向 BFS B F S 即可
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
struct node
{
int m[6][6],x,y,id,step;
};
ll Hash(node a)
{
ll ans=0;
for(int i=0;i<6;i++)
for(int j=0;j<=i;j++)
ans=ans*6ll+a.m[i][j];
return ans;
}
queue<node>que;
map<ll,int>M[2];
node s1,s2,now,temp;
int dx[]={-1,1,-1,1};
int dy[]={0,0,-1,1};
int bfs()
{
while(!que.empty())que.pop();
M[0].clear(),M[1].clear();
que.push(s1),que.push(s2);
M[0][Hash(s1)]=0,M[1][Hash(s2)]=0;
while(!que.empty())
{
now=que.front();que.pop();
int x=now.x,y=now.y,id=now.id,step=now.step;
ll h=Hash(now);
if(M[id^1].count(h))
{
int ans=M[id^1][h]+step;
if(ans<=20)return ans;
else continue;
}
if(step>=10)continue;
for(int i=0;i<4;i++)
{
int xx=x+dx[i],yy=y+dy[i];
if(xx<0||xx>5||yy<0||yy>xx)continue;
temp=now;
temp.x=xx,temp.y=yy;
swap(temp.m[x][y],temp.m[xx][yy]);
temp.step++;
h=Hash(temp);
if(M[id].count(h))continue;
M[id][h]=temp.step;
que.push(temp);
}
}
return 21;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
for(int i=0;i<6;i++)
for(int j=0;j<=i;j++)
{
scanf("%d",&s1.m[i][j]);
if(s1.m[i][j]==0)s1.x=i,s1.y=j;
s2.m[i][j]=i;
}
s2.x=s2.y=0;
s1.step=s2.step=0;
s1.id=0,s2.id=1;
int ans=bfs();
if(ans>20)printf("too difficult\n");
else printf("%d\n",ans);
}
return 0;
}