[蓝桥杯 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;
}
相关推荐
ゞ 正在缓冲99%…19 分钟前
leetcode75.颜色分类
java·数据结构·算法·排序
奋进的小暄1 小时前
贪心算法(15)(java)用最小的箭引爆气球
算法·贪心算法
Scc_hy1 小时前
强化学习_Paper_1988_Learning to predict by the methods of temporal differences
人工智能·深度学习·算法
巷北夜未央1 小时前
Python每日一题(14)
开发语言·python·算法
javaisC1 小时前
c语言数据结构--------拓扑排序和逆拓扑排序(Kahn算法和DFS算法实现)
c语言·算法·深度优先
爱爬山的老虎1 小时前
【面试经典150题】LeetCode121·买卖股票最佳时机
数据结构·算法·leetcode·面试·职场和发展
SWHL1 小时前
rapidocr 2.x系列正式发布
算法
雾月552 小时前
LeetCode 914 卡牌分组
java·开发语言·算法·leetcode·职场和发展
想跑步的小弱鸡2 小时前
Leetcode hot 100(day 4)
算法·leetcode·职场和发展
Fantasydg2 小时前
DAY 35 leetcode 202--哈希表.快乐数
算法·leetcode·散列表