0
点赞
收藏
分享

微信扫一扫

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

爱动漫建模 2022-04-03 阅读 69

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;
} 
举报

相关推荐

New Online Judge 1017

New Online Judge 1018

New Online Judge 1009

New Online Judge 1007

New Online Judge 1020

New Online Judge 1019

New Online Judge 1012

New Online Judge题解1006

多源BFS

0 条评论