题意:机器人要从一个m*n (1≤m,n≤20) 网格的左上角(1,1)走到右下角(m,n)。网格中的一些格子是空地(用0表示),其他格子是障碍(用1表示)。机器人每次可以往4个方向走一格,但不能连续地穿过k (0≤k≤20) 个障碍,求最短路长度。起点和终点保证是空地。(本段摘自《算法竞赛入门经典(第2版)》)
分析:
直接迭代加深搜索即可。加上最优性剪枝,即当前步数加上最少可能步数仍无法到达的话直接return。
代码:
#include <iostream>
#include <algorithm>
#include <fstream>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
#include <cmath>
#include <cctype>
#include <stack>
#include <set>
#include <map>
using namespace std;
const int maxn = 20 + 5, INF = 1e9;
const int dx[] = {0, 0, -1, 1}, dy[] = {1, -1, 0, 0};
int T, n, m, k, init;
int a[maxn][maxn], v[maxn][maxn];
bool flag;
int h(int x, int y)
{
return (n - x - 1) + (m - y - 1);
}
bool DFS(int x, int y, int step, int deep, int limit)
{
if (step > k)
return false;
if (deep == limit)
{
if (x == n - 1 && y == m - 1)
{
printf("%d\n", limit);
return true;
}
return false;
}
if (deep + h(x, y) > limit)
return false;
for (int i = 0; i < 4; ++i)
{
int xx = x + dx[i], yy = y + dy[i];
if (xx >= 0 && xx < n && yy >= 0 && yy < m && !v[xx][yy])
{
v[xx][yy] = 1;
if (a[xx][yy])
{
if (DFS(xx, yy, step + 1, deep + 1, limit))
return true;
}
else
{
if (DFS(xx, yy, 0, deep + 1, limit))
return true;
}
v[xx][yy] = 0;
}
}
return false;
}
int main()
{
scanf("%d", &T);
for (int C = 0; C < T; ++C)
{
flag = true;
scanf("%d%d%d", &n, &m, &k);
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
scanf("%d", &a[i][j]);
init = a[0][0];
for (int maxd = 1; maxd <= n * m; ++maxd)
{
memset(v, 0, sizeof(v));
v[0][0] = 1;
if (DFS(0, 0, init, 0, maxd))
{
flag = false;
break;
}
}
if (flag)
printf("-1\n");
}
return 0;
}