迷宫与陷阱--bfs+回路+剪枝

发布于:2025-06-07 ⋅ 阅读:(20) ⋅ 点赞:(0)

1.用bfs板子,同时会出现回路,但不能不用bo数组,要减去一部分没有用的回路

2.什么叫没有用的回路--因为我有无敌了,以前遇到的陷阱就能过了,那这就是有用的回路,

所以我记录(x,y)点的无敌状态步数(初始化为0),如果回来的步数大于之前的,那么很·有用,因为可能会过一些陷阱,如果小于等于那就纯纯浪费时间

P8673 [蓝桥杯 2018 国 C] 迷宫与陷阱 - 洛谷

#include<bits/stdc++.h>
using namespace std;
#define N 100011
typedef  long long ll;
typedef pair<int,int> pii;
int n,k;
char a[1005][1005];
int bo[1005][1005];
int kk[1005][1005];
int an=0x3f3f3f3f;
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
struct no
{
	int x,y,w;
};
queue<no> q;
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
   	cin>>n>>k;
   	for(int i=1;i<=n;i++)
   	{
   		for(int j=1;j<=n;j++) cin>>a[i][j];
	}
	bo[1][1]=1;
	q.push({1,1,0});
	while(q.size())
	{
		no t=q.front();
		q.pop();
		int x=t.x,y=t.y;
		if(x==n&&y==n)
		{
			cout<<bo[x][y]-1;return 0;
		}
		if(bo[x][y]>=n*n-1)
		{
			cout<<-1;
			return 0;
		}
		for(int i=0;i<4;i++)
		{
			int tx=x+dx[i],ty=y+dy[i];
			if(tx>=1&&tx<=n&&ty>=1&&ty<=n)
			{
				if(!bo[tx][ty])
				{
				if(a[tx][ty]=='.')
				{
					bo[tx][ty]=bo[x][y]+1;
					q.push({tx,ty,max(t.w-1,0)});
				}
				if(a[tx][ty]=='%')
				{
					bo[tx][ty]=bo[x][y]+1;
					kk[tx][ty]=k;
					q.push({tx,ty,k});
					a[tx][ty]='.';
				}
				if(a[tx][ty]=='X'&&t.w>0)
				{
					bo[tx][ty]=bo[x][y]+1;
					kk[tx][ty]=t.w-1;
					q.push({tx,ty,t.w-1});
				}	
				}
				else///最关键的一步,采用有用的回路 
				{
					if(a[tx][ty]=='%'&&k>kk[tx][ty])
				{
					bo[tx][ty]=bo[x][y]+1;
					kk[tx][ty]=k;
					q.push({tx,ty,k});
					a[tx][ty]='.';
				}
				if(a[tx][ty]=='X'&&t.w>0&&t.w-1>kk[tx][ty])
				{
					bo[tx][ty]=bo[x][y]+1;
					kk[tx][ty]=t.w-1;
					q.push({tx,ty,t.w-1});
				}
				if(a[tx][ty]=='.'&&max(t.w-1,0)>kk[tx][ty])
				{
					bo[tx][ty]=bo[x][y]+1;
					q.push({tx,ty,max(t.w-1,0)});
				}
				}
			}
		}
	}
	cout<<-1;
    return 0;
}

 

 


网站公告

今日签到

点亮在社区的每一天
去签到