New Online Judge P1128-绝地求生(多源bfs)

本文介绍了如何利用BFS算法解决一个类似游戏场景的问题,即在毒气扩散的地图中寻找从起点到安全区的最短路径。题目中存在多个毒气源,小H需要避开毒气并尽快抵达安全区。通过建立地图模型,使用两个队列分别存储小H的移动路径和毒气扩散路径,逐步更新地图状态,最终找到最短时间或判断无法到达安全区。
摘要由CSDN通过智能技术生成

P1128-绝地求生

传送门

题目描述:

小H所在的地方有毒气扩散,现在他必须赶去安全区。
他所在的地方可以用一个N∗M的地图表示。
	.表示空地,人和毒气都可以经过
	*表示毒气的地方(可能有多个地方有毒气)
	X表示障碍物,两者均不能经过
	S表示小H初始的位置
	D表示安全区(注意:安全区不会被毒气入侵)
小H每分钟可以往上下左右四个相邻位置移动,同时毒气也会从已有毒气的区域扩散到相邻的区域。
小H想知道到达安全区的最少时间,如果不能到达安全区,他将呼叫他的队友“HELP”。

输入格式:

输入第一行有两个数字分别为N和M
接下来输入N行,每行M个字符,表示小H所在区域的地图
输入保证S,D只出现一次。
1≤N,M≤50

输出格式:

如果可以到达安全区,输出一个整数,表示到达安全区的最少时间。
如果到达不了输出"HELP"(不含引号)

输入样例:

3 6
D...*.
.X.X..
....S.

输出格式:

6

思路:题目中说明毒圈位置不止一个,所以本题明显是一道多源bfs的题,故记录时间,在每分钟小H可以到达的地点入队之后,然后将这一分钟有那些毒圈可以向四周扩散,并将扩散的点入队(并且将入对的点时间+1),按照这个思路就可以解决本题。

菜鸟代码:

#include<bits/stdc++.h>
using namespace std;
const int N=55;
int dx[4]={0,0,-1,1};
int dy[4]={1,-1,0,0};
struct bs
{
    int x,y,s;		//(x,y)是位置,s代表时间
}t;
queue<bs>q,p;	//定义两个队列,q用于存放小H路径,p用于存放毒圈扩散路径
int n,m,ans;
char ma[N][N];		//存放地图
bool vis[N][N],flag;	//vis作为标记数组
void bfss(int x);
 
void bfs()		//广搜判断小H能否到达安全区
{
    while(!q.empty())
    {
        t=q.front();
        q.pop();
        if(ma[t.x][t.y]=='D')	//成功到达安全区
        {
            flag=true;		//将标记改为true,证明可以成功到达安全区
            ans=t.s;
            return;
        }
        for(int i=0;i<4;i++)	//对四个方向进行遍历
        {
            int tx=t.x+dx[i];
            int ty=t.y+dy[i];
            if(tx<0||ty<0||tx>=n||ty>=m||vis[tx][ty])	//判断小H能否过去
                continue;
            if(ma[tx][ty]=='.'||ma[tx][ty]=='D')
            {
                vis[tx][ty]=true;
                q.push({tx,ty,t.s+1});	//将下一步位置入队,时间+1分钟
            }
        }
        bfss(t.s); 		//毒圈进行扩散,注意只能是本分钟毒圈才可以扩散
    }
}
 
void bfss(int x)		//对每分钟毒圈位置向四周扩散的点进行广搜入队
{
    while(!p.empty())
    {
        bs t1=p.front();
        if(t1.s>x) return;		//不要忽略,每分钟可以扩散的毒圈入队,由本分钟毒圈入队的点在本分钟不能扩散,需要到下一分钟才可以扩散
        p.pop();
        for(int i=0;i<4;i++)
        {
            int tx=t1.x+dx[i];
            int ty=t1.y+dy[i];
            if(tx<0||ty<0||tx>=n||ty>=m)	//判断是否在地图以内
                continue;
            if(ma[tx][ty]=='.'&&!vis[tx][ty])	//
            {
                vis[tx][ty]=true;
                ma[tx][ty]='*';		//将扩散的地点标记为毒圈
                p.push({tx,ty,t1.s+1});		//入队,下一次毒圈扩散的时间在本分钟上加1
            }
        }
    }
}
 
int main()
{
    cin>>n>>m;		
    for(int i=0;i<n;i++)
    {
        scanf("%s",&ma[i]);
        for(int j=0;j<m;j++)
        {
            if(ma[i][j]=='S')	//将小H初始点入队
                q.push({i,j,0});
            if(ma[i][j]=='*')		//将初始地图中的毒圈点全部入队便于后面扩散
                p.push({i,j,0});
        }
    }
    bfs();
    if(flag) cout<<ans<<endl;
    else cout<<"HELP"<<endl;    
    return 0;
} 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值