HDOJ 1010 DFS加奇偶剪枝

题目链接:点击打开链接

题目大意为:给定一个n*m的矩阵和起点到终点的应该走的步数countMax,S为起点,D为终点, .为路求有没有一条路可以刚好经过countMax步到达终点


我做这个题目的时候,前面就是看成一个普通的DFS题,没想什么超时的问题,后来才发现按照普通的DFS去做会超时,于是我开始剪枝,参考了点击打开链接百度百科的奇偶剪枝。才解决了超时的问题。


奇偶剪枝的描述如下:

现假设起点为(sx,sy),终点为(ex,ey),给定t步恰好走到终点,
s
    
|
    
|
    
|
    
+
e
如图所示(“|”竖走,“—”横走,“+”转弯),易证abs(ex-sx)+abs(ey-sy)为此问题类中任意情况下,起点到终点的最短步数,记做step,此处step1=8;
s
 
 
+
 
|
+
   
|
    
+
e
如图,为一般情况下非 最短路径的任意走法举例,step2=14;
step2-step1=6,偏移路径为6,偶数(易证);

设t为要求到达的步数
则,若 t-[abs(ex-sx)+abs(ey-sy)] 结果为非偶数(奇数),则无法在t步恰好到达;
返回,false;
反之亦反。

原理补充可以,参考百度百科链接: 点击打开链接

代码实现如下:
package acm;
import java.util.Scanner;

public class P1010 {
	public static int f[][]={{0,-1},{0,1},{-1,0},{1,0}};
	public static int n,m,countMax;
	public static char a[][];
	public static boolean color[][];
	public static boolean t;
	
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		while(sc.hasNext()){
			n=sc.nextInt();
			m=sc.nextInt();
			countMax=sc.nextInt();
			if(n==0&&m==0&&countMax==0){
				break;
			}
			color=new boolean[n][m];
			a=new char[n][m];
			String b[]=new String[n];
			int x1=-1,y1=-1,x2=-1,y2=-1;
			for(int i=0;i<n;i++){
					b[i]=sc.next();
					a[i]=b[i].toCharArray();
					for(int j=0;j<a[i].length;j++){
					color[i][j]=true;
					if(a[i][j]=='S'){//记录S的位置
						x1=i;
						y1=j;
					}
					if(a[i][j]=='D'){//记录D的位置
						x2=i;
						y2=j;
					}
				}
			}
			if((countMax-Math.abs(x2-x1)-Math.abs(y2-y1))%2==1){
				//奇偶剪枝
				System.out.println("NO");
				continue;
			}
			t=false;
			color[x1][y1]=false;
			dfs(x1,y1,0);
			if(t){
				System.out.println("YES");
			}else{
				System.out.println("NO");
			}
		}
	}
	
	public static void dfs(int x,int y,int count){
		if(count>countMax){
			return;//当走过的步数超过了要求的步数,return
		}
		if(t){
			return;//当标记为真,return
		}
		if(count==countMax&&a[x][y]=='D'){
			t=true;//当刚好走到'D'且走过的步数等于要求的步数
			return;
		}
		for(int i=0;i<4;i++){
			//遍历该位置的四个方向
			int nx=x+f[i][0];
			int ny=y+f[i][1];
			if(nx>=0&&ny>=0&&nx<n&&ny<m){
				if(color[nx][ny]&&(a[nx][ny]=='.'||a[nx][ny]=='D')){
					color[nx][ny]=false;
					dfs(nx,ny,count+1);
					color[nx][ny]=true;//回溯
				}
			}
		}
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值