数据结构与算法-回溯算法

看了一天回溯算法,一路调试代码把自己都给转晕了,看着问题解出来的代码都很简短,但是总觉得不太能理解,一路调试也知道有点像是:

从起始位置出发,如果前面有几条岔路,那么先选择第一条,走下去,又有几条岔路,再选择第一条走下去,走过n个岔路口,一直都是选择第一条走下去,一路到底之后;

返回上一个路口,选择第二条一路走下去,又走过n个岔路口,到底之后,再返回上一个路口,选择第二条重复下去。

其实就是把所有可能的情况通过树的形式全部搜索出来,最后把所有符合的情况都列出来,或者如果是求最大值最小值,那么就比较所有情况的最大值最小值,当然,这个可以在把每一种情况走到底的时候,就比较出来一个最大值或最小值。比较典型的就是8皇后问题,0-1背包问题,还有就是正则表达式匹配问题。以下是前两种问题的代码,几行代码看了一整天,还感觉有点迷迷糊糊的,最后虽然是自己盲写出来的,但是总觉得似乎不是理解写出来的,而是看了一整天之后都把那十几行代码记熟了,我真是太菜了。

package com.freshbin.dataStructAndAlgo.chapter39.mycode;

/**
 * 八皇后问题
 * @date 2020/4/25 8:53
 */
public class EightQueen {

    private int n; // n个皇后
    int[] result;
    int count; // 总的可能摆放结果数

    public EightQueen(int n) {
        this.n = n;
        // n行n列的仿二维数组,数组中的值表示是第n列(从0开始数),比如a[0]=4,就表示第1行第5列已经放了皇后
        // 这里也可以用实际的二维数组,可能如果用二维数组会比较好理解一点,不过用一位数组比较取巧,代码少写一点
        result = new int[n];
        count = 0;
    }

    private void cal8queens() {
        diguiCal(0); // 从第1行开始放皇后
    }

    private void diguiCal(int row) {
        if(row == n) {
            printQueen();
            return;
        }

        // 从第一列往右边判断是否可以放置皇后,可以就直接放了,然后继续下一行,
        // 当下一行不满足放置条件的话,再不断回溯列,再回溯行
        for(int col = 0; col < n; col++) {
            if(canPlace(row, col)) {
                result[row] = col; // 如果满足条件,直接放置在该行该列
                diguiCal(row+1); // 直接跳去下一行继续走流程
            }
        }

    }

    /**
     * 判断当前行和列是否可以放置皇后
     * 纵向比较,比较该行该列上方的行是否已经存在皇后,再比较该行该列左上角和右上角是否存在皇后
     * @param row
     * @param col
     * @return
     */
    private boolean canPlace(int row, int col) {
        int leftUp = col - 1; // 左上角的列
        int rightUp = col + 1; // 右上角的列

        for(row = row - 1;row >= 0; row--) {
            if(result[row] == col) {
                return false;
            }
            if(leftUp >= 0 && result[row] == leftUp) {
                return false;
            }
            if(rightUp < n && result[row] == rightUp) {
                return false;
            }
            leftUp--;
            rightUp++;
        }
        return true;
    }

    private void printQueen() {
        // 打印结果
        System.out.println("=======第" + ++count + "种结果===========");

        for(int row = 0; row < result.length; row++) {
            for(int col = 0; col < n; col++) {
                if(result[row] == col) {
                    System.out.print("Q ");
                } else {
                    System.out.print("* ");
                }
            }
            System.out.println();
        }
    }

    public static void main(String[] arg) {
        EightQueen eightQueen = new EightQueen(8);
        eightQueen.cal8queens();

        System.out.println(Integer.MIN_VALUE);
    }
}
package com.freshbin.dataStructAndAlgo.chapter39.mycode;

import java.util.HashMap;

/**
 * @author freshbin
 * @date 2020/4/25 12:02
 */
public class PackageSolution {

    public HashMap<String, Integer> cacheMap;
    public int canPackageWeight;
    public int packageCurrentWeight;

    public PackageSolution(int canPackageWeight) {
        cacheMap = new HashMap<>();
        this.canPackageWeight = canPackageWeight;
        this.packageCurrentWeight = 0;
    }

    /**
     * @param currentIndex
     * @param currentWeight
     * @param items
     */
    public void knapsack(int currentIndex, int currentWeight, int[] items) {
       if(currentIndex >= items.length || currentIndex >= canPackageWeight) {
           if(currentWeight <= canPackageWeight) {
               packageCurrentWeight = Math.max(currentWeight, packageCurrentWeight);
               return;
           }
       }

       String key = currentIndex + "-" + currentWeight;
       if(cacheMap.containsKey(key)) {
           return;
       }
       cacheMap.put(key, 1);

       knapsack(currentIndex+1, currentWeight, items);

       if(currentWeight + items[currentIndex] <= canPackageWeight) {
           knapsack(currentIndex+1, currentWeight+items[currentIndex], items);
       }
    }

    public static void main(String[] arg) {
        int[] a = {2, 2, 4, 6, 3};
        PackageSolution packageSolution = new PackageSolution(9);
        packageSolution.knapsack(0, 0, a);
        System.out.println(packageSolution.packageCurrentWeight);
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值