算法学习——回溯法

  最近在准备CCF,所以一并把算法也一起复习了一下。下面的题目是老师让我们按照回溯法书上的模板写的题,纪录一下。

我太菜辽,呜呜呜。

package com.lianup.suanfa.Backtrack;

/**
 *题目:小明从n*n矩阵的左下方走到右上方,并且不能够走过矩阵从右到左的对角线的上方,每次只能向上或者向右走一步
 * 求出所有走法
 * 要求:按照回溯法的格式写
 */
public class Test2 {

    /**
     * 用来存放可行解的数组,idnex[layer][0]和index[layer][1]分别表示当解空间深度为layer时的所在坐标
     */
    int[][] index;
    int n;
    int sum;
    StringBuilder res;
    int[][] gone = new int[][]{{-1,0},{0,1}};

    /**
     * 启动函数
     * @param n
     */
    public void cacu(int n){
        this.n = n;
        index = new int[n*2][2];
        index[0][0] = n-1;
        index[0][1] = 0;
        res = new StringBuilder();
        backtrack(1);
    }


    /**
     * 回溯法主函数
     * @param layer 当前扩展节点在解空间中的深度
     */
    public void backtrack(int layer){
        // 此问题回溯法解空间一共有2*n层,因为每个向上和向下走都有走和不走两种选择
        if(layer >= 2*n-1){
            update();
            return;
        }

        for(int i = 0;i < 2;i++){

            // x,y分别为上一次选择后的横纵坐标
            int x = index[layer-1][0];
            int y = index[layer-1][1];
            index[layer][0] = x + gone[i][0];
            index[layer][1] = y + gone[i][1];

            if(bound(layer)){
                backtrack(layer+1);
            }
        }

    }

    /**
     * 限界函数,判断是否越界
     * @param layer
     * @return
     */
    public boolean bound(int layer){

        if(index[layer][0] < 0 || index[layer][0] >= n || index[layer][1] < 0 || index[layer][1] >= n){
            return false;
        }
        if(index[layer][1] < n - index[layer][0] - 1){
            return false;
        }
        return true;
    }


    /**
     * 输出函数
     * @return
     */
    public String output(){
        return res.toString();
    }

    /**
     * 更新函数
     */
    public void update(){
        sum++;
        for(int i = 0;i < n;i++){
            res.append(index[i][0] + "," + index[i][1] + " ");
        }
        res.append("\n");
    }


}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值