问题:
小狗能否从起点S,经过时间T,恰好到达终点D。
条件:
1、Therefore the doggie had to arrive at the door on exactly the T-th second.(小狗必须在T时刻准时到达出口)
2、In every second, he could move one block to one of the upper, lower, left and right neighboring blocks.(每一秒,小狗可以向上下左右四个方向移动一步)
3、He could not stay at one block for more than one second,(他只能在一个位置上待一秒钟)
4、nor could he move into a visited block.(他也不能再回到已经走过的位置)
3、算法设计:
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、超时。
小狗能否从起点S,经过时间T,恰好到达终点D。
条件:
1、Therefore the doggie had to arrive at the door on exactly the T-th second.(小狗必须在T时刻准时到达出口)
2、In every second, he could move one block to one of the upper, lower, left and right neighboring blocks.(每一秒,小狗可以向上下左右四个方向移动一步)
3、He could not stay at one block for more than one second,(他只能在一个位置上待一秒钟)
4、nor could he move into a visited block.(他也不能再回到已经走过的位置)
3、算法设计:
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之后,停止搜索。
本题利用深搜,深搜原理
利用java面向对象来解决:
package cn.hdu;
import java.util.Scanner;
public class CopyOfP1010 {
static int m,n,t,sum;
static Block[][] blocks;
static int[][] dir={ {0,-1},
{-1,0}, {1,0},
{0,1} };
static int time=-1;
public static void main(String[] args) {
Scanner sc= new Scanner(System.in);
while (sc.hasNext()) {
n = sc.nextInt();
m = sc.nextInt();
t = sc.nextInt();
if(n==0&&m==0&&t==0)
return;
time=-1;
sum=0;
blocks = new Block[n][m];
Block state=null;
Block end=null;
for (int i = 0; i < n; i++) {
String str = sc.next();
for (int j = 0; j < m; j++) {
char c=str.charAt(j);
blocks[i][j] = new Block(i, j, c);
if(c!='X')
sum++;
if(c=='S')
state=blocks[i][j];
if(c=='D')
end=blocks[i][j];
}
}
//防护数据(OJ输入合理,无用)
if(state==null||end==null){
System.out.println("NO");
continue;
}//奇偶性剪枝
if(((end.x+state.x+end.y+state.y+t)%2==1)){
System.out.println("NO");
continue;
}//可行性剪枝
if(sum<t){
System.out.println("NO");
continue;
}
//深搜
dfsBlock(state,end);
if(end.time==t)
System.out.println("YES");
else
System.out.println("NO");
}
}
private static boolean dfsBlock(Block block,Block end) {
time++;//记时
block.isVisit=true;//涂黑
if(block.c=='D'){//到达
if(time==t){
block.time=time;
return true;
}
return false;
}
if(time>=t)//时间约束
return false;
//奇偶性剪枝
if(((end.x+block.x+end.y+block.y+(t-time))%2==1))
return false;
//上下左右移动
for (int i = 0; i < dir.length; i++) {
int x=block.x+dir[i][0];
int y=block.y+dir[i][1];
if(x>=0&&x<n && y>=0&&y<m && !blocks[x][y].isVisit && blocks[x][y].c!='X'){
if(dfsBlock(blocks[x][y],end)){
return true;
}
blocks[x][y].isVisit=false;
time--;
}
}
return false;
}
static class Block{
int x,y,time;//位置,时间
char c;//字符
boolean isVisit;//是否走过
public Block(int x, int y, char c) {
this.x = x;
this.y = y;
this.c = c;
isVisit=false;
time=0;
}
}
}