百练4130:Saving Tang Monk

英文题目巨烦

紧接着百练4115:鸣人和佐助和百练4116拯救行动的变形

题目连接:http://bailian.openjudge.cn/practice/4130/

#include<iostream>
#include<algorithm>
#include<fstream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<cmath>
#include<cctype>
#include<vector>
#include<limits.h>
#include<queue>

using namespace std;

#define N 110

int INF=(int)1e10;

int dir[4][2]= {{0,1},{1,0},{0,-1},{-1,0}};

char s[N][N];   //输入的字符串矩阵
int p[N][N];      //有蛇的位置会显示编号
int mark[N][N][10]; //拿过所有钥匙后的最小时间,11表示的可能就是那9把钥匙吧

int n,m,ans;

struct mmp
{
    int x,y,t,id,snake;   //坐标、时间、钥匙、和杀死的蛇
    bool operator<(const mmp &w) const
    {
        return t>w.t;
    }
    mmp(int xx,int yy,int tt,int ii,int ss):x(xx),y(yy),t(tt),id(ii),snake(ss) {}
};

void bfs(int x,int y)
{
    int i,h;
    priority_queue<mmp>q;
    mmp next= {0,0,0,0,0};
    q.push(mmp(x,y,0,1,0));
    mark[x][y][1]=0;
    while(!q.empty())
    {
        mmp cur=q.top();
        q.pop();
        if(s[cur.x][cur.y]=='T'&&cur.id==m+1)
        {
            ans=min(ans,cur.t);
            continue;
        }
        for(i=0; i<4; i++)
        {
            next.x=cur.x+dir[i][0];
            next.y=cur.y+dir[i][1];
            next.t=cur.t+1;
            next.snake=cur.snake;
            next.id=cur.id;
            if(next.x<0||next.x>=n||next.y<0||next.y>=n||s[next.x][next.y]=='#')
                continue;
            if(s[next.x][next.y]=='S')  //判断是否杀死过蛇,只杀一次,杀一次时间+1
            {
                h=p[next.x][next.y];
                if((next.snake&(1<<h))==0)
                {
                    next.snake|=(1<<h);
                    next.t++;
                }
            }
            if(next.id==s[next.x][next.y]-'0') //只有前几把钥匙拿到手后才能拿下一把钥匙
            {
                next.id++;
            }
            if(mark[next.x][next.y][next.id]>next.t) //拿过某一把钥匙后的最小时间
            {
                mark[next.x][next.y][next.id]=next.t;
                q.push(next);
            }
        }
    }
}

int main()
{
    int i,j,k,l,a,b;
    while(scanf("%d%d",&n,&m)&&!(n==0&&m==0))
    {
        memset(p,0,sizeof(p));
        for(i=0,k=0; i<n; i++)
        {
            scanf("%s",s[i]);
            for(j=0; j<n; j++)
            {
                if(s[i][j]=='K')
                {
                    a=i;
                    b=j;
                }
                if(s[i][j]=='S')
                {
                    p[i][j]=k++;
                }
                for(l=0; l<10; l++)
                {
                    mark[i][j][l]=INF;
                }
            }
        }
        ans=INF;
        bfs(a,b);
        if(ans==INF)
            printf("impossible\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值