题目链接:http://172.18.66.54:50015/problem.php?id=1466
题目描述
这里是一片n*m荒芜之体,穿过一个沼泽地就必须消耗一罐氧气(沼泽不会消失,没有氧气罐就不能穿过沼泽)。
你是否能够逃出这里。
'*': 空地
'+':经过可以获得一罐氧气 (重复经过可以重复获得)
'#':沼泽地(重复经过会重复消耗)
'S':起点
'T':终点
你的背包最多带4罐氧气, 用掉可以继续获得。
输入
多样例(n, m输入为0 0结束)
第一行:n m (n, m<=100)
2-n行:输入地图。
输出
输出是否能够从起点到达终点
是:"YES"并且输出最少的步数
否: "NO"
样例输入
5 5
S****
+****
+****
#####
****T
1 5
+*S#T
1 3
S#T
0 0
样例输出
YES
8
YES
6
NO
思路:Bfs跑一下就可以了。用dis[i][j][k]记录在位置(i, j)有k罐氧气的最少步数。如果下个状态(i, j, k)的步数< dis[i][j][k]就加入队列
#include<bits/stdc++.h>
using namespace std;
const int N=105;
const int M=0x3f3f3f3f;
int dp[N][N][8];
char mp[N][N];
int d[2][4]= {0,1,0,-1,1,0,-1,0};
struct node
{
int x,y,n;//位置 x y 氧气瓶数 n
};
int main()
{
int i,j,n,m,t;
int sx,sy,ex,ey;//起点 终点
while(scanf("%d %d",&n,&m), n*m)
{
for(int i=1; i<=n; i++)
{
scanf("%s",mp[i]+1);
for(int j=1; j<=m; j++)
{
if(mp[i][j]=='S') sx=i,sy=j;
else if(mp[i][j]=='T') ex=i,ey=j;
for(int k=0; k<=5; k++) dp[i][j][k]=M;//初始化
}
}
queue<node>q;
dp[sx][sy][0]=0;
q.push(node{sx,sy,0});
while(!q.empty())//BFS
{
node t=q.front();
q.pop();
for(int i=0; i<4; i++)//四个方向
{
int x=t.x+d[1][i];
int y=t.y+d[0][i];
int c=t.n;
if(x>n||y>m||x<1||y<1) continue;//出界
switch(mp[x][y])
{
case 'S'://起点
case '*'://空地
if(dp[x][y][c]>dp[t.x][t.y][c]+1)//秒数比较
{
dp[x][y][c]=dp[t.x][t.y][c]+1;
q.push(node{x,y,c});
}
break;
case 'T'://终点
if(dp[x][y][c]>dp[t.x][t.y][c]+1)//秒数比较
{
dp[x][y][c]=dp[t.x][t.y][c]+1;
q.push(node{x,y,c});
}
break;
case '#'://毒气
if(c>0&&dp[x][y][c-1]>dp[t.x][t.y][c]+1)//氧气瓶数>0 氧气瓶-1
{
dp[x][y][c-1]=dp[t.x][t.y][c]+1;
q.push(node{x,y,c-1});
}
break;
case '+'://氧气
if(c<5&&dp[x][y][c+1]>dp[t.x][t.y][c]+1)//氧气瓶+1 秒数+1
{
dp[x][y][c+1]=dp[t.x][t.y][c]+1;
q.push(node{x,y,c+1});
}
else if(c==4&&dp[x][y][c]>dp[t.x][t.y][c]+1)//不拿氧气瓶 比较秒数
{
dp[x][y][c]=dp[t.x][t.y][c]+1;
q.push(node{x,y,c});
}
break;
default://其他
break ;
}
}
}
int ans=M;
for(int k=0; k<=4; k++)//寻找终点最小值
ans=min(ans,dp[ex][ey][k]);
if(ans>=M)
{
printf("NO
");
}
else
{
printf("YES
");
printf("%d
",ans);
}
}
}