HDU 6171 Admiral(hash+双向bfs)

125 篇文章 0 订阅
15 篇文章 0 订阅

Description

给出一个六层的地图,从上到下第 i i 层有i个块,以 (i,j) ( i , j ) 表示第 i+1 i + 1 层从左到右第 j+1 j + 1 个块的坐标,一个块可以和与其相邻的块交换,两个块相邻当且仅当其某维坐标相同,第 i i 层块编号均为i1,现在给出一个地图初始状态,要把编号为 0 0 的块移动到(0,0)处,问最少步数

Input

第一行一整数 T T 表示用例组数,每组用例输入一个地图的初始状态

Output

如果可以在20以内把 0 0 移动到(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 ~5,共 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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值