hdu6171 Admiral
传送门
题意
有一个(6)行的舰队,第(i(1leq ileq 6))行有(i)艘战舰,共有(21)艘战舰,其中编号为(i(0leq ileq 5))的战舰有((i+1))艘,编号为(0)的那艘战舰上有司令,这艘战舰可以和周围四个方位的战舰交换位置:左上,上,下,右下。舰队的终态为编号为(i(0leq ileq 5))的战舰全部在第((i+1))行,给出始态,计算从初态到终态的最短步数,如果步数超过(20),输出"too difficult"。
题解
已知始态和终态,使用双向(bfs),队列中到达状态所需的步数不超过(10)步,状态通过(map)进行哈希映射成(LL)。
#include<bits/stdc++.h>
#define LL long long
using namespace std;
//四个方向:左上,上,下,右下
int T,dir[4][2]={{-1,-1},{-1,0},{1,0},{1,1}};
struct node{
int x,y;
//flag==0表示正向,flag==1表示反向
int state[6][6],flag,step;
};
map<LL,int> mp[2];
queue<node> q;
LL Hash(node a){
LL ans=0;
for(int i=0;i<6;i++){
for(int j=0;j<=i;j++){
ans=ans*6+a.state[i][j];
}
}
return ans;
}
void bfs(){
while(!q.empty()){
node a=q.front();
q.pop();
if(mp[!a.flag].count(Hash(a))){
printf("%d
",mp[!a.flag][Hash(a)]+a.step);
return;
}
for(int k=0;k<4;k++){
node b=a;
int tx=b.x+dir[k][0];
int ty=b.y+dir[k][1];
if(tx<0 || tx>5 || ty<0 || ty>tx) continue;
swap(b.state[b.x][b.y],b.state[tx][ty]);
b.x=tx;
b.y=ty;
b.step++;
if(b.step>10) continue;
if(mp[b.flag].count(Hash(b))) continue;
mp[b.flag][Hash(b)]=b.step;
q.push(b);
}
}
printf("too difficult
");
}
int main(){
scanf("%d",&T);
while(T--){
node a,b;
for(int i=0;i<6;i++){
for(int j=0;j<=i;j++){
scanf("%d",&a.state[i][j]);
if(a.state[i][j]==0){
a.x=i;
a.y=j;
}
b.state[i][j]=i;
}
}
a.flag=a.step=0;
b.x=b.y=b.step=0;
b.flag=1;
mp[0].clear();
mp[1].clear();
while(!q.empty()) q.pop();
q.push(a);
q.push(b);
mp[0][Hash(a)]=mp[1][Hash(b)]=0;
bfs();
}
}