HDU - 3085 Nightmare Ⅱ(双向bfs)

本文探讨了一个迷宫逃脱问题,采用双向BFS算法解决男孩和女孩在鬼魂追击下如何汇合的挑战。通过分析角色速度、迷宫布局及实时判断鬼魂位置,实现高效路径寻找。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:点击查看

题目大意:给出一个迷宫,一个男孩和一个女孩还有两只鬼,男孩每秒钟走3格,女孩每秒钟走1格,鬼每秒钟向四周分裂2格,问男孩和女孩能否在鬼占领迷宫之前汇合,能的话输出汇合时间,否则输出-1

题目分析:双向bfs模板题,不过在我看来双向bfs和单向bfs没什么区别,就是格式上有点不一样,对于这个题目每次男孩bfs一次,然后女孩bfs一次,注意实时判断当前格子是否已经被鬼占领,每次向外扩展的时候也不需要用vis数组标记重复了,只需要在原迷宫的基础上打上自己的特殊符号即可,只要另一方遍历到该符号即代表两人相遇,就可以及时返回了

这个题目有一个需要注意的地方,一开始没仔细看题目,想当然的以为M代表的是女生,G代表的是男生,结果正好相反了,当时调了有点时间,回去仔细读了一遍题才发现的。。

代码:

#include<iostream>
#include<cstdio> 
#include<string>
#include<ctime>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<sstream>
using namespace std;

typedef long long LL;

const int inf=0x3f3f3f3f;

const int N=810;

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

int n,m,k,step,ans;

char maze[N][N];

struct Node
{
	int x,y;
	Node(int X,int Y)
	{
		x=X;
		y=Y;
	}
	Node(){}
}ghost[2];

queue<Node>gg,mm;

bool check(int x,int y)
{
	if(x<0||y<0||x>=n||y>=m)
		return false;
	if(maze[x][y]=='X')
		return false;
	for(int i=0;i<2;i++)
		if(step*2>=abs(x-ghost[i].x)+abs(y-ghost[i].y))
			return false;
	return true;
}

bool bfsgg()
{
	for(int tt=1;tt<=3;tt++)
	{
		queue<Node>q(gg);
		while(!q.empty())
		{
			Node cur=q.front();
			q.pop();
			gg.pop();
			if(!check(cur.x,cur.y))
				continue;
			for(int i=0;i<4;i++)
			{
				int xx=cur.x+b[i][0];
				int yy=cur.y+b[i][1];
				if(!check(xx,yy))
					continue;
				if(maze[xx][yy]=='M')
					continue;
				if(maze[xx][yy]=='G')
					return true;
				maze[xx][yy]='M';
				gg.push(Node(xx,yy));
			}
		}
	}
	return false;
}

bool bfsmm()
{
	queue<Node>q(mm);
	while(!q.empty())
	{
		Node cur=q.front();
		q.pop();
		mm.pop();
		if(!check(cur.x,cur.y))
			continue;
		for(int i=0;i<4;i++)
		{
			int xx=cur.x+b[i][0];
			int yy=cur.y+b[i][1];
			if(!check(xx,yy))
				continue;
			if(maze[xx][yy]=='G')
				continue;
			if(maze[xx][yy]=='M')
				return true;
			maze[xx][yy]='G';
			mm.push(Node(xx,yy));
		}
	}
	return false;
}

bool solve()
{
	while(!gg.empty())
		gg.pop();
	while(!mm.empty())
		mm.pop();
	step=k=0;
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			if(maze[i][j]=='G')
				mm.push(Node(i,j));
			else if(maze[i][j]=='M')
				gg.push(Node(i,j));
			else if(maze[i][j]=='Z')
			{
				ghost[k].x=i;
				ghost[k].y=j;
				k++;
			}
	while(!mm.empty()&&!gg.empty())
	{
		step++;
		if(bfsgg()||bfsmm())
		{
			ans=step;
			return true;
		}
	}
	return false;
}

int main()
{
//	freopen("input.txt","r",stdin);
	int w;
	cin>>w;
	while(w--)
	{
		
		scanf("%d%d",&n,&m);
		for(int i=0;i<n;i++)
			scanf("%s",maze[i]);
		if(solve())
			printf("%d\n",ans);
		else
			printf("-1\n");
	}
	
	
	
	
	
	
	
	
	
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Frozen_Guardian

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值