[蓝桥杯2018决赛]迷宫与陷阱

本文介绍了一种使用三维数组标记已访问状态的广度优先搜索(BFS)算法,该算法用于解决包含无敌值增益的迷宫问题。通过定义一个三维数组vis[a][b][c]来跟踪每个位置(a,b)在不同无敌值c的情况下是否已被访问过。

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

这道题关键点在于走过的点可能还会重复走(比如去另一个方向获得无敌值再回来),所以用传统的bfs绝对不行,因此需要设一个三维数组vis[a][b][c] 标记点(a,b)在无敌值为c的时候是否已经走过,走过的话就不再走了。只有当去获得无敌值时才会重复走。

#include<bits/stdc++.h>
using namespace std;
int n,k,flag,vis[1005][1005][15]; //vis[a][b][k]表示(a,b)点在无敌值为k的时候是否走过,如果已经走过了那么以后就不会再重复走。再走的话说明是获取到了无敌值 
								//用这种三维数组标记巧妙的避免了两个点之间的死循环无限走 
char mapp[1005][1005];
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
struct node{
	int x;
	int y;
	int wd;
	int step;	
};
void bfs(int x,int y)
{
	node p;
	queue<node> q;
	p.x=x;
	p.y=y;
	p.wd=0;
	p.step=0;
	vis[1][1][0]=1;
	q.push(p);
	while(!q.empty())
	{
		node u=q.front();
		q.pop();
		if(u.x==n && u.y==n)
		{
			flag=1;
			cout<<u.step<<endl;
			return;
		}
		for(int i=0;i<4;i++)
		{
			int tx=u.x+dx[i];
			int ty=u.y+dy[i];
			if(tx>=1&&tx<=n&&ty>=1&&ty<=n&&mapp[tx][ty]!='#')
			{
				if(mapp[tx][ty]=='%'&&vis[tx][ty][k]==0) //经过能获得无敌的地方 
				{
					vis[tx][ty][k]=1; 
					node pp;
					pp.x=tx;
					pp.y=ty;
					pp.step=u.step+1;
					pp.wd=k;
					q.push(pp);
				}
				else
				{
					if(mapp[tx][ty]=='X' && u.wd>0 && vis[tx][ty][u.wd-1]==0)
					{
						vis[tx][ty][u.wd-1]=1;
						node pp;
						pp.x=tx;
						pp.y=ty;
						pp.step=u.step+1;
						pp.wd=u.wd-1;
						q.push(pp);
					}
					else if(mapp[tx][ty]=='.' && u.wd>0 && vis[tx][ty][u.wd-1]==0) 
					{
						vis[tx][ty][u.wd-1]=1;
						node pp;
						pp.x=tx;
						pp.y=ty;
						pp.step=u.step+1;
						pp.wd=u.wd-1;
						q.push(pp);
					}
					else if(mapp[tx][ty]=='.' && u.wd==0 && vis[tx][ty][0]==0)
					{
						vis[tx][ty][0]=1;
						node pp;
						pp.x=tx;
						pp.y=ty;
						pp.step=u.step+1;
						pp.wd=0;
						q.push(pp);
					}
				} 
			}
		}
	}
}
int main()
{
	while(cin>>n>>k)
	{
		flag=0;
		memset(vis,0,sizeof(vis));
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				cin>>mapp[i][j];
			}
		}
		bfs(1,1);
		if(flag==0)
			cout<<"-1"<<endl;
	}
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

henulmh

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

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

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

打赏作者

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

抵扣说明:

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

余额充值