题目描述:
机器人从一个(m imes n)网格的左上角((1,1))走到右下角((m,n))。网格中的一些格子是空地,用(0)表示,其他格子是障碍,用(1)表示。机器人每次可以往四个方向走一格,但不能连续地穿越(k)个障碍,求最短路的长度。起点和中点保证是空地。
思路:
还是BFS求最短路,但是因为不能连续穿过(k)个障碍,所以与普通BFS不同的是这里需要考虑到达某个格子时已经连续走了几个障碍,而且即使格子已经被访问过,但如果新的访问耗费的障碍数能小于此前访问耗费的障碍数,也是可以访问的(与普通BFS的区别在这里)。后面这点是我开始没有想到,后面对着udebug上的测试数据调的时候才发现问题的,还有就是要考虑一下(m=1,n=1)的初始条件。
代码:
#include <iostream>
#include <queue>
#include <utility>
#include <algorithm>
#include <memory.h>
using namespace std;
const int maxn = 20 + 2;
int b[maxn][maxn];
int d[maxn][maxn];
int obs[maxn][maxn];
int m, n, k;
const int dr[] = { 0, -1, 0, 1};
const int dc[] = { 1, 0, -1, 0};
pair<int, int> walk(pair<int, int> u, int i){
pair<int, int> v;
v.first = u.first + dr[i];
v.second = u.second + dc[i];
return v;
}
void solve(){
queue<pair<int, int> > q;
q.push(make_pair(1, 1));
memset(d, -1, sizeof(d));
memset(obs, 0, sizeof(obs));
d[1][1] = 0;
while(!q.empty()){
pair<int, int> u = q.front(); q.pop();
for(int i = 0; i < 4; ++i){
pair<int, int> v = walk(u, i);
if(v.first == m && v.second == n) { //抵达终点
d[v.first][v.second] = d[u.first][u.second] + 1;
printf("%d
", d[v.first][v.second]);
return;
}
if(v.first > 0 && v.first <= m && v.second > 0 && v.second <= n && (d[v.first][v.second]<0||d[v.first][v.second]>0&&obs[u.first][u.second]+1<obs[v.first][v.second])){ //没有出界&&(没有被访问过||访问过但是当前路径到达这个点时耗费的障碍数更少)
d[v.first][v.second] = d[u.first][u.second] + 1;//更新起点到达该网格的距离
if(b[v.first][v.second] == 1){ //如果网格是一个障碍
obs[v.first][v.second] = obs[u.first][u.second] + 1;//获得当前网格连续经过的障碍数
if(obs[v.first][v.second] > k) { d[v.first][v.second] = -1; obs[v.first][v.second] = 0; continue;}//如果障碍数超过限制,将这个网格标记为没有访问,重新将其状态初始化。
}
else obs[v.first][v.second] = 0; //不是网格就清零连续障碍数
q.push(v);
}
}
}
if(d[m][n] < 0) printf("-1
");//最终没能访问到终点,输出-1
else printf("%d
", d[m][n]); //这里是应对m=1,n=1的边界条件
}
int main(){
//freopen("uva1600_in.txt", "r", stdin);
//freopen("uva1600_out.txt", "w", stdout);
int T; scanf("%d", &T);
while(T--){
scanf("%d%d%d", &m, &n, &k);
for(int i = 1; i <= m; ++i){
for(int j = 1; j <= n; ++j)
scanf("%d", &b[i][j]);
}
solve();
}
}