數據結構與算法-回溯算法

看了一天回溯算法,一路調試代碼把自己都給轉暈了,看着問題解出來的代碼都很簡短,但是總覺得不太能理解,一路調試也知道有點像是:

從起始位置出發,如果前面有幾條岔路,那麼先選擇第一條,走下去,又有幾條岔路,再選擇第一條走下去,走過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);
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章