hdu 5025——Saving Tang Monk

48 篇文章 0 订阅
13 篇文章 0 订阅

题意:孙悟空要去救唐僧,有M个钥匙,只有拿到了第k种钥匙才能拿第k+1种钥匙,必须拿到所有钥匙才能救人。迷宫里面有蛇,杀死一条蛇要花费两秒。求救唐僧需要的最少时间。

思路:记录下当前拿到的钥匙数量,蛇最多五条,用状态压缩记录杀死蛇的状态

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;

struct pos
{
    int x,y,k,s;
    pos(){}
    pos(int x,int y,int k,int s):x(x),y(y),k(k),s(s){}
};
int n,m;
int dp[105][105][10][1<<5];
int dir[4][2]={-1,0,0,1,1,0,0,-1};
int snack[105][105];
char matrix[105][105];

void bfs(pos start)
{
    queue<pos> q;
    q.push(start);
    while(!q.empty())
    {
        pos tt=q.front();
        q.pop();
   //     cout<<tt.x<<' '<<tt.y<<' '<<tt.k<<endl;
        for(int d=0;d<4;++d)
        {
            int ii=tt.x+dir[d][0];
            int jj=tt.y+dir[d][1];
            if(ii<0||ii>=n||jj<0||jj>=n)continue;
            if(matrix[ii][jj]=='#')continue;
            int kk=tt.k;
            int ss=tt.s;
            if(matrix[ii][jj]-'0'==tt.k+1)kk++;
            if(matrix[ii][jj]=='S')
            {
                ss|=1<<snack[ii][jj];
            }
            int add=ss==tt.s?1:2;
            if(dp[ii][jj][kk][ss]==-1||dp[ii][jj][kk][ss]>dp[tt.x][tt.y][tt.k][tt.s]+add)
            {
                dp[ii][jj][kk][ss]=dp[tt.x][tt.y][tt.k][tt.s]+add;
                q.push(pos(ii,jj,kk,ss));
            }
        }
    }
}

int main()
{
  //  freopen("data.txt","r",stdin);
    while(scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0)break;
        memset(dp,-1,sizeof(dp));
        int totsn=0;
        pos start;
        pos Tang;
        for(int i=0;i<n;++i)
        {
            scanf("%s",matrix[i]);
            for(int j=0;j<n;++j)
            {
                if(matrix[i][j]=='K'){start.x=i;start.y=j;start.k=0;start.s=0;}
                else if(matrix[i][j]=='S'){snack[i][j]=totsn++;}
                else if(matrix[i][j]=='T'){Tang.x=i;Tang.y=j;}
            }
        }
        dp[start.x][start.y][0][0]=0;
        bfs(start);
        int ans=-1;
        for(int i=0;i<=(1<<totsn)-1;++i)
        {
            if(dp[Tang.x][Tang.y][m][i]==-1)continue;
            if(ans==-1)ans=dp[Tang.x][Tang.y][m][i];
            else ans=min(ans,dp[Tang.x][Tang.y][m][i]);
        }
        if(ans==-1)printf("impossible\n");
        else printf("%d\n",ans);
    }
    return 0;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值