1. 程式人生 > >動態規劃本質理解:01背包問題

動態規劃本質理解:01背包問題

復雜 pan int out key 版本 println 滾動數組 背包

題目描述:01背包問題 w:重量 v:價值 cap:承重

參考代碼:

package Dp;

import org.junit.Test;

/**
 * 01背包問題 w:重量 v:價值 cap:承重
 * 
 * @author Tongkey
 */
public class Backpack {
    public int[][] result;

    /**
     * 遞歸解法,時間復雜度為O(2^n)
     * 
     * @param w
     *            重量
     * @param v
     *            價值
     * 
@param cap * 承重 * @param n * 數量 * @param curCap * 當前的重量 總重量 = 當前的重量+剩余的重量 * @param index * 當前的下標值 * @return */ public int maxValueRe(int[] w, int[] v, int cap, int n, int curCap, int index) {
if (curCap > cap) { return 0; } if (index >= n) { return 0; } return Math.max(maxValueRe(w, v, cap, n, curCap + w[index], index + 1) + v[index], maxValueRe(w, v, cap, n, curCap, index + 1)); } /** * 備忘錄解法(自頂向下),時間復雜度O(n*cap),空間復雜度O(n*cap) * *
@param w * 重量 * @param v * 價值 * @param cap * 承重 * @param n * 數量 * @param curCap * 當前的重量 總重量 = 當前的重量+剩余的重量 * @param index * 當前的下標值 * @return */ public int maxValueMemory(int[] w, int[] v, int cap, int n, int curCap, int index) { if (curCap > cap) { return 0; } if (index >= n) { return 0; } if (result[index][curCap] > 0) { return result[index][curCap]; } result[index][curCap] = Math .max(maxValueRe(w, v, cap, n, curCap + w[index], index + 1) + v[index], maxValueRe(w, v, cap, n, curCap, index + 1)); return result[index][curCap]; } @Test public void testMaxValueMemory(){ int[] w = { 42, 25, 30, 35, 42, 21, 26, 28 }; int[] v = { 261, 247, 419, 133, 391, 456, 374, 591 }; int n = 8; int cap = 297; result = new int[n][cap + 1]; int maxValueRe = maxValueMemory(w, v, cap, n, 0, 0); System.out.println(maxValueRe); System.out.println("----------------------"); } /** * 自底向上(非遞歸寫法),時間復雜度O(n*cap),空間復雜度O(n*cap) * * @param w * @param v * @param cap * @param n * @param curCap * @param index * @return */ public int maxValueDp(int[] w, int[] v, int cap, int n, int curCap, int index) { result[0][0] = 0; // 第一行 for (int i = 1; i <= cap; i++) { if (i >= w[0]) result[0][i] = v[0]; } // 第一列 for (int i = 1; i < n; i++) { result[i][0] = 0; } for (int i = 1; i < n; i++) { for (int j = 1; j <= cap; j++) { // 默認值,不取index當前的重量值 result[i][j] = result[i - 1][j]; if (j >= w[i]) result[i][j] = Math.max(result[i][j], result[i - 1][j - w[i]] + v[i]); } } return result[n - 1][cap]; } /** * 自底向上(利用滾動數組非遞歸寫法優化),時間復雜度O(n*cap),空間復雜度O(cap) * @param w * @param v * @param cap * @param n * @param curCap * @param index * @return */ public int maxValueDpMod(int[] w, int[] v, int cap, int n, int curCap, int index) { result[0][0] = 0; // 第一行 for (int i = 1; i <= cap; i++) { if (i >= w[0]) result[0][i] = v[0]; } for (int i = 1; i < n; i++) { for (int j = 1; j <= cap; j++) { result[i % 2][j] = result[(i - 1) % 2][j]; if (j >= w[i]) result[i % 2][j] = Math.max(result[i % 2][j], result[(i - 1) % 2][j - w[i]] + v[i]); } } return Math.max(result[0][cap], result[1][cap]); } /** * 把二維數組優化為一維數組版本 * @param w * @param v * @param n * @param cap * @return */ public int maxValueDp2(int[] w, int[] v, int n, int cap) { // 給定物品的重量w價值v及物品數n和承重cap int[] d = new int[cap + 1]; for (int i = 0; i < n; i++) { for (int j = cap; j >= w[i]; j--) { d[j] = Math.max(d[j], d[j - w[i]] + v[i]); } } return d[cap]; } @Test public void testMaxValueRe() { int[] w = { 42, 25, 30, 35, 42, 21, 26, 28 }; int[] v = { 261, 247, 419, 133, 391, 456, 374, 591 }; int n = 8; int cap = 297; result = new int[2][cap + 1]; int maxValueRe = maxValueDpMod(w, v, cap, n, 0, 0); System.out.println(maxValueRe); System.out.println("----------------------"); } }

動態規劃本質理解:01背包問題