看了一天回溯算法,一路调试代码把自己都给转晕了,看着问题解出来的代码都很简短,但是总觉得不太能理解,一路调试也知道有点像是:
从起始位置出发,如果前面有几条岔路,那么先选择第一条,走下去,又有几条岔路,再选择第一条走下去,走过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);
}
}