[蓝桥杯 2018 国 C] 迷宫与陷阱

题目链接:迷宫与陷阱

这道题目跟我们平时做的bfs不同的是 多了一个"无敌状态" 那么也就需要我们去比较有无敌状态经过陷阱和不走陷阱的最少的步数。

先说说我之前的思路吧:

开一个vis[N][N]表示走到(x,y) 这个点所需最小的步数,

再开一个st[N][N]表示这个无敌状态还能持续多少步,假设%这个点为0,一步步增多,超过k结束

这个思路是正确的,但。。。。

没错,内存超限了。。。

想看原代码的话如下:

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N =1005;
char a[N][N];
int vis[N][N];
int st[N][N];
int n,k,sx,sy,ex,ey;
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
struct node{
	int x,y;
};

void bfs(int sx,int sy){
	queue<node>q;
	q.push({sx,sy});
	while(!q.empty()){
		int x=q.front().x;
		int y=q.front().y;
		q.pop();
		for(int i=0;i<4;i++){
			int nx=x+dx[i];
			int ny=y+dy[i];
			if(nx<1||nx>n||ny<1||ny>n)continue;
			if(a[nx][ny]=='#')continue;
			if(vis[nx][ny]<0x3f/2&&st[nx][ny]<st[x][y])continue;
			if(st[x][y]>k-1&&a[nx][ny]=='X')continue;
			st[nx][ny]=min(st[nx][ny],st[x][y]+1);
			vis[nx][ny]=vis[x][y]+1;
			q.push({nx,ny});
		}
	}
}

int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>n>>k;
	sx=sy=1;
	ex=ey=n;
	memset(vis,0x3f,sizeof(vis));
	memset(st,0x3f,sizeof(st));
	vis[sx][sy]=0;
	for(int i=1;i<=n;i++){
		string s;cin>>s;
		for(int j=1;j<=n;j++){
			a[i][j]=s[j-1];
			if(a[i][j]=='%'){
				st[i][j]=0;
			}
		}
	}

	if(a[sx][sy]=='.')bfs(sx,sy);

//	for(int i=1;i<=n;i++){
//		for(int j=1;j<=n;j++){
//			cout<<vis[i][j]<<" ";
//		}
//		cout<<"\n";
//	}

	if(vis[ex][ey]==0x3f)cout<<-1<<"\n";
	else cout<<vis[ex][ey]<<"\n";

	return 0;
}

那么怎么考虑将这个无敌状态伴随着呢?那么我们可以考虑将这个状态放到struct结构体里面,因为queue中提取的x,y就是我要遍历的这个点,所以当前的状态就正好可以表示,那么同样我也可以将步数塞进去,那么此时就少了st数组,那么vis数组的作用在于记录当前这个点的无敌状态。

为什么还要用vis记录无敌状态呢?

这就考虑到跟上一个点比较了,原本的图遍历我们只需走一次即可,那么出现了新的无敌状态就要考虑我是不是可以先去拿这个无敌状态然后往回走再去走陷阱呢?

复制代码
5 3
...XX
##%#.
...#.
.###.
.....

就如例题这个,那么就要回溯,回溯的条件就是当前的无敌值一定是比我要去的无敌值大。

因为不可能走比自己无敌值小的点(遍历过的点)

代码附上:

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N =1005;
char a[N][N];
int vis[N][N];//走到该点的无敌步数多少
int n,k,sx,sy,ex,ey;
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
struct node{
	int x,y,w,st;
};
bool flag=false;

void bfs(int sx,int sy){
	queue<node>q;
	q.push({sx,sy,0,0});
	vis[sx][sy]=0;
	while(!q.empty()){
		node t=q.front();
		q.pop();
		if(t.x==ex&&t.y==ey){
			flag=true;
			cout<<t.st<<"\n";
			return;
		}
		for(int i=0;i<4;i++){
			int nx=t.x+dx[i];
			int ny=t.y+dy[i];
			if(nx<1||nx>n||ny<1||ny>n)continue;
			if(a[nx][ny]=='#')continue;
			if(t.w==0&&a[nx][ny]=='X')continue;
			int w=max(0,t.w-1);//计算目前的无敌值
			if(a[nx][ny]=='%'){
				w=k;
			}//2 1 0
			if(vis[nx][ny]>=w)continue;//回溯的条件
			vis[nx][ny]=w;
			q.push({nx,ny,w,t.st+1});
		}
	}
}

int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>n>>k;
	sx=sy=1;
	ex=ey=n;
	memset(vis,-1,sizeof(vis));
	vis[sx][sy]=0;
	for(int i=1;i<=n;i++){
		string s;cin>>s;
		for(int j=1;j<=n;j++){
			a[i][j]=s[j-1];
		}
	}

	if(a[sx][sy]=='.')bfs(sx,sy);

//	for(int i=1;i<=n;i++){
//		for(int j=1;j<=n;j++){
//			cout<<vis[i][j]<<" ";
//		}
//		cout<<"\n";
//	}

	if(!flag)cout<<-1<<"\n";

	return 0;
}
相关推荐
黑岚樱梦2 小时前
代码随想录打卡day23:435.无重叠区间
算法
Kuo-Teng2 小时前
Leetcode438. 找到字符串中所有字母异位词
java·算法·leetcode
gihigo19983 小时前
MATLAB使用遗传算法解决车间资源分配动态调度问题
算法·matlab
墨染点香3 小时前
LeetCode 刷题【138. 随机链表的复制】
算法·leetcode·链表
却道天凉_好个秋3 小时前
目标检测算法与原理(一):迁移学习
算法·目标检测·迁移学习
兮山与4 小时前
算法24.0
算法
晓北斗NorSnow4 小时前
机器学习核心算法与学习资源解析
学习·算法·机器学习
hans汉斯5 小时前
【计算机科学与应用】基于BERT与DeepSeek大模型的智能舆论监控系统设计
大数据·人工智能·深度学习·算法·自然语言处理·bert·去噪
多喝开水少熬夜6 小时前
损失函数系列:focal-Dice-vgg
图像处理·python·算法·大模型·llm