原题地址:点击打开链接
一个石子在有阻碍物的迷宫里滑行,迷宫有起点和终点,当然也有阻碍物,
现在已知起点和终点,求石子从起点到达终点的最短路,如果无法到达,则输出-1。
石子移动的具体规则如下:
1、开始时,石子在起点s处
2、运动方向可以是水平或垂直的,不能斜方向运动
3、最开始的时候,你可以将石子向上下左右任意一个方向抛,如果与它相邻的点是障碍物的话除外
4、一旦石子开始运动,有三种可能:
a、遇到障碍物,石子会停在障碍物的前一格,障碍物会消失
b、如果出界,游戏失败
c、到达终点,游戏结束并成功
5、如果移动的次数超过10次,将认为游戏是失败的
输入w,h, 输出最短路
其中输入的数字表示:
0 | 路 |
1 | 阻碍物 |
2 | 起点 |
3 | 终点 |
2 <= w <= 20, 1 <= h <= 20
Sample Input
2 1
3 2
6 6
1 0 0 2 1 0
1 1 0 0 0 0
0 0 0 0 0 3
0 0 0 0 0 0
1 0 0 0 0 1
0 1 1 1 1 1
6 1
1 1 2 1 1 3
6 1
1 0 2 1 1 3
12 1
2 0 1 1 1 1 1 1 1 1 1 3
13 1
2 0 1 1 1 1 1 1 1 1 1 1 3
0 0
Sample Output
1
4
-1
4
10
-1
答案:
#include <iostream>
#define MAX_W 20
#define MAX_H 20
#define INF 4000
using namespace std;
int m[MAX_H][MAX_W], w, h;
int sx, sy, ans;
int dx[] = {0, 0, 1, -1}, dy[] = {1, -1, 0, 0};
void dfs(int n, int x, int y)
{
if(11 == n || n >= ans)
return ;
for(int i = 0; i < 4; i ++){
int nx = x + dx[i], ny = y + dy[i], flag = 0;
if(!(nx >= 0 && nx < h && ny >= 0 && ny < w))
continue;
if(1 == m[nx][ny])
continue;
do{
if(3 == m[nx][ny]){
ans = n;
return ;
}
else if(1 == m[nx][ny]){
flag = 1;
break;
}
nx += dx[i], ny += dy[i];
}while(nx >= 0 && nx < h && ny >= 0 && ny < w);
if(flag){
m[nx][ny] = 0;
dfs(n + 1, nx - dx[i], ny - dy[i]);
m[nx][ny] = 1;
}
}
}
void solve()
{
ans = INF;
dfs(1, sx, sy);
if(ans != INF)
cout << ans << endl;
else
cout << "-1" << endl;
}
int main()
{
while(cin >> w >> h){
for(int i = 0; i < h; i ++)
for(int j = 0; j < w; j ++){
cin >> m[i][j];
if(2 == m[i][j])
sx = i, sy = j;
}
if(w || h)
solve();
else
break;
}
return 0;
}
这道题花了不少时间,犯得主要错误是认为石子不能走回头路,导致没有输出正确的结果,优点是运用了剪枝,算法还算比较高效的,只要找到了最短的路,就结束递归了