HDOJ1010 Tempter of the Bone

问题:

小狗能否从起点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;
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值