oj1001 BFS 剪枝函数

首先,该题很明显要使用递归来计算,为了是算法更有效,使用剪枝函数。

(1)若已剩的步数小于两点之间x的间距和y的间距之和,则不可能达到,该点可以减去。

(2)因为奇数点(x+y为奇数)到奇数点,偶数点到偶数点的步数为偶数,奇数到偶数的步数为奇数,则可以利用这个判断起点到终点是否可达。

import java.util.Scanner;

public class Main_1010 {
    static char[][] status;
    static boolean[][] flag;
    static  int T,N,M,x2,y2;
    static boolean success;
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        N = in.nextInt();
        M = in.nextInt();
        T = in.nextInt();
        in.nextLine();
        int x = 0, y =0;
        while(N != 0 && M !=0 && T !=0){
            status = new char[N][M];
            flag = new boolean[N][M];
            success = false;
            for(int i = 0; i < N; i++){
                String s = in.nextLine();
                for(int j = 0; j < M; j++){
                    status[i][j] = s.charAt(j);
                    if(status[i][j] == 'S'){
                        x = i;
                        y = j;
                    }
                    if(status[i][j] == 'D'){
                        x2 = i;
                        y2 = j;
                    }
                }
            }
            visit(x,y,0);
            if(success){
                System.out.println("YES");
            }else{
                System.out.println("NO");
            }
            N = in.nextInt();
            M = in.nextInt();
            T = in.nextInt();
            in.nextLine();

        }

    }

    public static void visit(int x,int y,int count){
        if(count > T){
            return;
        }
        //判断当前剩下步数是否足够
        if((T-count) < Math.abs(x2-x)+Math.abs(y2-y)){
            return;
        }
        //奇偶剪枝
        if((T-count)%2 +(x+y+x2+y2)%2 ==1){
            return;
        }
        if(status[x][y] == 'D' && count == T){
            success = true;
            return;
        }
        if(status[x][y] == '.' || status[x][y] == 'S'){
            flag[x][y] = true;
            //向上走
            if(x - 1 >= 0 && !flag[x-1][y]){
                visit(x-1,y,count+1);
            }
            //向下走
            if(x + 1 < N && !flag[x+1][y]){
                visit(x+1,y,count+1);
            }
            //向左走
            if(y -1 >= 0 && !flag[x][y-1]){
                visit(x,y-1,count+1);
            }
            //向右走
            if(y + 1 < M && !flag[x][y+1]){
                visit(x,y+1,count+1);
            }
            flag[x][y] = false;
        }
    }

}


 特别注意的是,每次全局变量都需要重新初始化,而且success只有在到达D时才变为true,当不满足时不用改变,因为达到D后,函数还是要完成之前压栈的函数,之后的值会覆盖原来的success值。

参考 https://blog.csdn.net/u014174811/article/details/41293209

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值