非常有意思的一道最短路径题. 地图中有障碍物, 障碍物可以通过, 但不能连续通过K个障碍物. 实现起来也不难, 就是在BFS的时候给结点添加一个属性来记录已连续通过的障碍物个数就行了.
比较值得注意的地方是, 如果用map存储自定义类型, 而且自定义类型中的还有多个同等重要的成员时, 重载<运算符的时候必须小心一些, 应该类似这样的形式:
friend bool operator<(const Point & p1, const Point & p2) {
if ( p1.x != p2.x ) return p1.x < p2.x;
else if ( p1.y != p2.y ) return p1.y < p2.y;
else return p1.k < p2.k;
}
而不能为了简洁好看写成这样:
friend bool operator<(const Point & p1, const Point & p2) {
return (p1.x < p2.x && p1.y < p2.y && p1.k < p2.k);
}
以上两个函数所得到的结果是完全不同的, 第二种看上去很像是可行的,
但并不是我们需要的逻辑, 设想一下就知道了 : 比如当两个点 p1, p2的x值相等时,
那么p1 < p2 和p2 < p1都会是false, 但 p1 和 p2 是不一定相等的 , 因此不能这么写
AC代码如下
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <list>
#include <cassert>
#include <iomanip>
#pragma warning(disable:4996) //关掉4996警告
/*
Uva 439
关键 : 求最短路径 <- BFS
*/
using namespace std;
const int MAXN = 9;
struct Point {
int y, x;
int k; // 当前已通过的障碍物数
Point(int _y = 0, int _x = 0, int _k = 0): x(_x), y(_y), k(_k){}
friend bool operator<(const Point & p1, const Point & p2) {
if ( p1.x != p2.x ) return p1.x < p2.x;
else if ( p1.y != p2.y ) return p1.y < p2.y;
else return p1.k < p2.k;
}
friend bool operator==(const Point & p1, const Point & p2) {
return (p1.x == p2.x && p1.y == p2.y && p1.k == p2.k);
}
};
int M, N, K;
int Move[4][2] = { { 1, 0 },{ 0, 1 },{ 0, -1 },{ -1, 0 } };
bool G[21][21];
bool isAvailable(const Point & p) {
return (p.x >= 1 && p.x <= N && p.y >= 1 && p.y <= M );
}
int BFS(const Point & Start, const Point & End) {
Point cur;
map<Point, int> Dis;
map<Point, bool> isVisited;
queue<Point> Q;
Q.push(Start);
Dis[Start] = 0;
bool isFound = false;
while ( !Q.empty() ) {
cur = Q.front( ); Q.pop( );
if ( cur.x == End.x && cur.y == End.y ) {
isFound = true;
break;
}
isVisited[cur] = true;
Point next;
for ( int i = 0; i < 4; i++ ) {
next = Point(cur.y + Move[i][1], cur.x + Move[i][0], cur.k);
if ( G[next.y][next.x] ) next.k++;
else next.k = 0;
if ( isAvailable(next) &&
!isVisited[next] && // isVisited总返回true
next.k <= K ) {
Q.push(next);
Dis[next] = Dis[cur] + 1;
}
}
}
if( isFound ) return Dis[cur];
else return -1;
}
int main( ) {
//freopen("input.txt", "r", stdin);
int T;
cin >> T;
string from, to;
Point Start, End;
for ( int i = 0; i < T; i++ ) {
memset(G, 0, sizeof(G));
cin >> M >> N >> K;
for ( int i = 1; i <= M; i++ ) {
for ( int j = 1; j <= N; j++) {
cin >> G[i][j];
}
}
Start = Point(1, 1);
End = Point(M, N);
cout << BFS(Start, End) << endl;
}
//system("pause");
return 0;
}