对照书上的中文理解起来最快。
3
2 5
0
0 1 0 0 0
0 0 0 1 0
4 6
1
0 1 1 0 0 0
0 0 1 0 1 1
0 1 1 1 1 0
0 1 1 1 0 0
2 2
0
0 1
1 0
理解一下上面的样例输入:
3 表示数据集一共用三个。
下面的三组数据集中,以第一个数据集举例。
// Patrol Robot, ACM/ICPC Hanoi 2006, UVa1600
// 陈锋
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <functional>
#include <queue>
using namespace std;
#define _for(i, a, b) for (int i = (a); i < (b); ++i)
bool inRange(int x, int l, int r) {
return (l > r) ? inRange(x, r, l) : (l <= x && x <= r);
}
struct Point {
int x, y;
Point(int x = 0, int y = 0) : x(x), y(y) {}
};
typedef Point Vector;
Vector operator+(const Vector &A, const Vector &B) {
return Vector(A.x + B.x, A.y + B.y);
}
bool operator==(const Point &a, const Point &b) {
return a.x == b.x && a.y == b.y;
}
const int MAXN = 24;
int M, N, K, Grid[MAXN][MAXN], vis[MAXN][MAXN][MAXN];
bool isValid(const Point &p) {
return inRange(p.x, 0, M - 1) && inRange(p.y, 0, N - 1);
}
Vector dirVs[4] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
struct Stat {
Point pos;
int turbo;
};
int &getVisd(const Stat &s) { return vis[s.pos.x][s.pos.y][s.turbo]; }
int solve() {
Stat s;
Point dest(M - 1, N - 1);
s.pos.x = 0;
s.pos.y = 0;
s.turbo = 0;
memset(vis, -1, sizeof(vis));
queue<Stat> q;
q.push(s);
vis[s.pos.x][s.pos.y][s.turbo] = 0;
while (!q.empty()) {
const Stat &f = q.front();
q.pop();
const int &fd = getVisd(f);
if (f.pos == dest)
return fd;
assert(f.turbo <= K);
_for(i, 0, 4) {
Point np = f.pos + dirVs[i];
if (!isValid(np))
continue;
int isBlock = Grid[np.x][np.y];
if (isBlock && f.turbo + 1 > K)
continue;
Stat ns = {np, (isBlock ? (f.turbo + 1) : 0)};
int &d = getVisd(ns);
if (d == -1) {
d = fd + 1;
q.push(ns);
}
}
}
return -1;
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
scanf("%d%d%d", &M, &N, &K);
_for(i, 0, M) _for(j, 0, N) scanf("%d", &(Grid[i][j]));
int ans = solve();
printf("%d\\n", ans);
}
}
// 1627141 LA3670 Patrol Robot Accepted C++ 0.003
// 2015-01-15 03:05:38
需要处理几个疑问:
1、为什么 vis 是三维数组?
遍历到当前的某一个点的时候,第三维是用的涡轮加速器的数量。一个涡轮加速器可以过一个障碍,两个就可以过两个连续的障碍物。这个三维数组,比如 vis[s.pos.x][s.pos.y][s.turbo]
中,存放的是当前这个点并且使用了 s.turbo 个涡轮加速器之后的当前最优值。
2、getVisd(const Stat &s) 函数如何理解?
这个函数名取得不好。这里的 d 可能是 distance 的意思。表示 s 状态下的最优路径的距离。为什么这个值就是最优的呢?因为这里使用的是队列,并且,这个队列模拟的是 bfs,所谓 bsf,就是一圈一圈往外扩散,所以,如果当前所在的这一圈有一个是终点了,那么,最优值自然就出来了。