MYF

UVa 1600 Patrol Robot

题目链接

UVa 1600

方法:BFS (三层标记)

题目分析

题目大意

给定一个m*n的矩阵,0表示可以通行,1表示有障碍。机器人在无障碍时可以自由通行,但是如果粉碎障碍穿过的话,最多只能连续穿多k个障碍。问,机器人从(1,1)到(m,n)最少需要多少步?

解析

如果没有障碍,直接采用BFS,很容易找出解,但是如果有破墙这个事情,则增加一维vis数组,记录状态。

记录状态——关于vis标记数组(在此感谢Isco学长)

vis这个数组很强大,可以用0/1表示是否访问,也可以用0/steps表示走到当前位置的步数,如果从0开始,就先置-1/INF。此外,vis这个数组不局限于二维,如本题中,使用的是三维形式,到(x,y)点再记录一下已连破的障碍物数量z。利用这三个状态(x、y、z),记录经过破z堵墙到(x,y)点的最小步数。在代码中,请关注两处含**的注释。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <vector>
#include <iomanip>
#include <cstring>
#include <iostream>
#include <algorithm>
#define PI acos(-1)
#define debug printf("Hi----------\n")
#define eps 1e-8
#define INF 0x3f3f3f3f
#pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long ll;
using namespace std;
#define maxn 10005
int mp[30][30];
int vis[30][30][50];
int mx[]={-1,1,0,0};
int my[]={0,0,-1,1};
int n,m,k,t;
struct point{
//表示坐标、移动到该坐标的步数、已连续穿过的障碍数
int x,y,moves,z;
point(){}
point(int a,int b,int c,int d){
x=a;
y=b;
moves=c;
z=d;
}
};
bool inmap(int x,int y){
return x>0&&y>0&&x<=m&&y<=n;
}
void bfs(){
memset(vis, INF, sizeof(vis));
point a(1,1,0,0);
queue<point>q;
q.push(a);
vis[a.x][a.y][0]=0;
while (!q.empty()) {
point tmp=q.front();
q.pop();

//**只对到该点的步数最少的点进行BFS扩散,否则忽略
if (vis[tmp.x][tmp.y][tmp.z]<tmp.moves)
continue;

if (tmp.x==m&&tmp.y==n) {
printf("%d\n",tmp.moves);
return;
}

point tp;
for (int i=0; i<4; i++) {
tp.x=tmp.x+mx[i];
tp.y=tmp.y+my[i];
tp.moves=tmp.moves+1;

if (tmp.z==k&&mp[tp.x][tp.y]==1) //已经连续破墙k次,无法再破墙
continue;
else if (mp[tp.x][tp.y]==1) //继续破墙
tp.z=tmp.z+1;
else //走到无障碍物的地方
tp.z=0;

//**如果该点在图内,并且连破z堵墙走到该点的步数更少,则更新vis[][][]
if (inmap(tp.x, tp.y)&&vis[tp.x][tp.y][tp.z]>tp.moves) {
vis[tp.x][tp.y][tp.z]=tp.moves;
q.push(tp);
}
}
}
printf("-1\n");
return;
}
int main(){
scanf("%d",&t);
for (int cas=0; cas<t; cas++) {
memset(mp, 0, sizeof(mp));
scanf("%d%d%d",&m,&n,&k);
for (int i=1; i<=m; i++)
for (int j=1; j<=n; j++)
scanf("%d",&mp[i][j]);
bfs();
}
}