- 题目:
n*m的方格,某些时刻某些方格危险。求(1,1)到(n,m)的最短时间。注意,每个时间单位必须走,不能停。
- 思路:
每个点由(x,y,t)三维描述,vis数组也使用三维记录,-1表示危险,0代表可到达,>0代表最短步数。
取(1,1,0),x、y、t同时扩展,判断条件,修改vis,入队列
- 注意:
1.时间维的range与x、y不同,没有危险的情况下最大200,由于有危险的时间<=100,所以时间维最大为3e2
2.int vis[][][]可以优化为bool vis[][][],危险和已到达标记为true,不需要额外记录步数,因为在不能停且一步耗费一个时间单位的情况下,步数=point.t
3.if判断的条件:边界为n,m而非100 vis合法的条件为==0而非>=0
- 代码:
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
//二维平面上的点
struct Point{
int x;
int y;
int t;
};
const int maxn=1e2+5;
int dx[]{0,0,-1,1};
int dy[]{1,-1,0,0};
int vis[maxn][maxn][3*maxn];//-1代表危险 0代表可到达 >0代表最短步数
int n,m,t;
int main(){
cin>>n>>m>>t;
int r,c,a,b;
while(t--){
cin>>r>>c>>a>>b;
for(int i=a;i<=b;i++)
vis[r][c][i]=-1;
}
queue<Point> q;
q.push({1,1,0});
while(!q.empty()){
Point now=q.front(); q.pop();
//特判终点
if(now.x==n&&now.y==m){
cout<<vis[now.x][now.y][now.t]<<endl;
// cout<<now.t<<endl;
break;
}
//扩展
for(int i=0;i<4;i++){
int x=now.x+dx[i],
y=now.y+dy[i],
t=now.t+1;
//1.不出边界 2.没到过 3.不危险
if(x>=1&&x<=n&&y>=1&&y<=m&&vis[x][y][t]==0){
vis[x][y][t]=vis[now.x][now.y][now.t]+1;
q.push({x,y,t});
}
}
}
return 0;
}