大意:奥林匹克冰球运动的一种变体,给定你一个特定的迷宫,出口以及入口,从出口到入口最小走几步。
思路:
(1)不可用BFS,冰球每次撞击障碍物时,障碍物会消失。而BFS会导致整个迷宫状态的改变,所以只能用DFS。
(2)当冰球是运动时,撞击障碍物,然后停下,需要回溯。静止时,不可能向有障碍物的方向走。
(3)冰球不向普通的走法一样是一步一步走,而是一条直线的走。它可能在运动的过程中会超出边界,这就需要判断,只有继续递归调用时,步数才会加1。
CODE:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
const int SIZE = 21;
const int INF = 0x3f3f3f3f;
int maze[SIZE][SIZE];
int min_step, step;
int bx, by;
const int dx[] = {1,-1,0,0};
const int dy[] = {0,0,-1,1};
int n, m;
void init()
{
memset(maze, INF, sizeof(maze));
step = 0;
min_step = 0x3f3f3f3f;
bx = by = 0;
}
int check(int x, int y)
{
if(x >= 0 && y >= 0 && x < n && y < m )
return 1;
return 0;
}
void dfs(int x, int y, int step)
{
if(step > 10) return ; //剪枝
for(int i = 0; i < 4; i++)
{
int xx = x+dx[i];
int yy = y+dy[i];
if(!check(xx, yy)) continue; //超出边界
if(maze[xx][yy] == 1) continue; //静止状态而旁边是障碍物
while(maze[xx][yy] == 0)
{
xx += dx[i];
yy += dy[i];
if(!check(xx, yy)) break; //超出边界
}
if(check(xx, yy))
{
if(maze[xx][yy] == 3) //走到目标
{
if(step+1 < min_step)
{
min_step = step+1; //状态的更新
}
}
if(maze[xx][yy] == 1) //运动时遇到障碍物并停下。
{
maze[xx][yy] = 0;
dfs(xx-dx[i], yy-dy[i], step+1); //不可用++step
maze[xx][yy] = 1; //回溯
}
}
}
}
int main()
{
while(~scanf("%d%d", &m, &n), m, n)
{
init();
for(int i = 0;i < n; i++)
{
for(int j = 0; j < m; j++)
{
scanf("%d", &maze[i][j]);
if(maze[i][j] == 2)
{
bx = i;
by = j;
maze[i][j] = 0; //切记
}
}
}
dfs(bx, by, step);
if(min_step <= 10) printf("%d\n", min_step); //判断是否在十步之内
else printf("-1\n");
}
return 0;
}
#include <stdlib.h>
#include <string.h>
using namespace std;
const int SIZE = 21;
const int INF = 0x3f3f3f3f;
int maze[SIZE][SIZE];
int min_step, step;
int bx, by;
const int dx[] = {1,-1,0,0};
const int dy[] = {0,0,-1,1};
int n, m;
void init()
{
memset(maze, INF, sizeof(maze));
step = 0;
min_step = 0x3f3f3f3f;
bx = by = 0;
}
int check(int x, int y)
{
if(x >= 0 && y >= 0 && x < n && y < m )
return 1;
return 0;
}
void dfs(int x, int y, int step)
{
if(step > 10) return ; //剪枝
for(int i = 0; i < 4; i++)
{
int xx = x+dx[i];
int yy = y+dy[i];
if(!check(xx, yy)) continue; //超出边界
if(maze[xx][yy] == 1) continue; //静止状态而旁边是障碍物
while(maze[xx][yy] == 0)
{
xx += dx[i];
yy += dy[i];
if(!check(xx, yy)) break; //超出边界
}
if(check(xx, yy))
{
if(maze[xx][yy] == 3) //走到目标
{
if(step+1 < min_step)
{
min_step = step+1; //状态的更新
}
}
if(maze[xx][yy] == 1) //运动时遇到障碍物并停下。
{
maze[xx][yy] = 0;
dfs(xx-dx[i], yy-dy[i], step+1); //不可用++step
maze[xx][yy] = 1; //回溯
}
}
}
}
int main()
{
while(~scanf("%d%d", &m, &n), m, n)
{
init();
for(int i = 0;i < n; i++)
{
for(int j = 0; j < m; j++)
{
scanf("%d", &maze[i][j]);
if(maze[i][j] == 2)
{
bx = i;
by = j;
maze[i][j] = 0; //切记
}
}
}
dfs(bx, by, step);
if(min_step <= 10) printf("%d\n", min_step); //判断是否在十步之内
else printf("-1\n");
}
return 0;
}