hdu 1010 java版

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");
}
}
}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值