1、题目概述:
该题是一道典型的迷宫类搜索题目,为了达到运行效率的要求,需要采取剪枝的策略。所谓剪枝,就是根据题目的特性,将一些没必要的搜索过程省去,从而提高算法的时间效率。
2、问题:
小狗能否从起点S,经过时间T,恰好到达终点D
3、算法设计:
搜索方式主要有两种,即深搜(DFS,Deep-First-Search)和广搜(BFS,Breadth-First-Search)。显然,改题目适合采用深搜算法。
接下来我们需要设计剪枝策略,以提高算法时间效率。
接下来我们需要设计剪枝策略,以提高算法时间效率。
1、奇偶性剪枝
首先,我们先来解释一下奇偶剪枝。
若有一迷宫,将迷宫的每一个位置用0或1来标记(x+y为偶数时为0,x+y为奇数时为1)
0 1 0 1 0
1 0 1 0 1
0 1 0 1 0
1 0 1 0 1
从上面的例子中,我们观察后发现,每一个位置的值必然与其相邻位置的值相反。也就是说我们要从S位置走到D位置,如果S上的值和D上的值相同,必然经过偶数
所以,我们设计的奇偶剪枝如下:
如果起点S上的值和终点D上的值相同,时间T为奇数,则直接判断不可达,从而省去了搜索的过程,提高了算法的效率。
如果起点S上的值和重点D上的值相异,时间T为偶数,则直接判断不可达。
2、剩余可走区域小于时间。
即能够走得位置数量比时间少,那么将所有的位置走过之后,剩下的时间将无路可走,所以直接判断不可达,省去搜索过程。
3、越界。
当越界之后,则停止继续搜索。
4、超时。
搜索路径长度超过时间T之后,停止搜索
比较好的搜索+剪枝
三个剪枝:
1.奇偶性剪枝,题目要求确切在t这个时间点上到达目的地,而且小狗不能作停留,那么如果给出的时间t,和起点到终点的距离奇偶性不等,则一定不可达。
2.可达性剪枝,如果从起点到终点毫不绕行要k步,地图上能走的地方也比k步少,毫无疑问,也不可能。
3.可达性剪枝2,搜索时可能离目标越来越远,以致再回头已经来不及走了,所以在搜索到中途某个位置时,如果所剩时间比毫不绕行走到目标还小,那么也不用再往下搜了。
import java.util.*;
public class Main{
static final int MaxN=8;
static char[][] map = new char[MaxN][MaxN];
static int n,m,t,Dx = 0,Dy = 0;
static int dir[][] = {{0,1},{0,-1},{-1,0},{1,0}};
static boolean inMap(int r, int c)
{
return r>=0 && c>=0 && r<n && c<m;
}
static boolean DFS(int r, int c, int d)
{
if(d<Math.abs(r-Dx)+Math.abs(c-Dy)) return false;
if(d == 0)
{
if(r == Dx && c == Dy)
return true;
return false;
}
map[r][c] = 'X';
int _r,_c,i;
for(i=0; i<4; i++)
{
_r = r+dir[i][0];
_c = c+dir[i][1];
if(inMap(_r,_c) && map[_r][_c] != 'X')
{
if (DFS(_r,_c,d-1)) return true;
}
}
map[r][c] = '.';
return false;
}
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
String tmp = new String();
int i,j,wallNum, Sx = 0, Sy = 0;
while(true)
{
n = in.nextInt();
m = in.nextInt();
t = in.nextInt();
if(n==0 && m==0 && t==0)
break;
wallNum = 0;
for( i=0; i<n; i++)
{
if(in.hasNext())
tmp = in.next();
map[i] = tmp.toCharArray();
for( j=0; j<m; j++)
if(map[i][j] == 'S')
{
Sx = i;
Sy = j;
}
else if(map[i][j] == 'D')
{
Dx = i;
Dy = j;
}
else if(map[i][j] == 'X')
wallNum++;
}
if(((Sx+Sy+Dx+Dy+t)&1)==1 || n*m-wallNum-1<Math.abs(Dx-Sx)
+Math.abs(Dy-Sy))
{
System.out.println("No");
continue;
}
if(DFS(Sx,Sy,t))
{
System.out.println("Yes");
}
else
{
System.out.println("No");
}
}
}
}