01揹包問題(Java)

題目

有 N 件物品和一個容量是 V 的揹包。每件物品只能使用一次。java

第 i 件物品的體積是 vi,價值是 wi。code

求解將哪些物品裝入揹包,可以使這些物品的整體積不超過揹包容量,且總價值最大。
輸出最大價值。class

輸入格式
第一行兩個整數,N,V,用空格隔開,分別表示物品數量和揹包容積。import

接下來有 N 行,每行兩個整數 vi,wi,用空格隔開,分別表示第 i 件物品的體積和價值。遍歷

輸出格式
輸出一個整數,表示最大價值。im

數據範圍
0<N,V≤1000
0<vi,wi≤1000
輸入樣例
4 5
1 2
2 4
3 4
4 5
輸出樣例:
8next

思想

經典動態規劃題
物品個數n,揹包總容量v
c[]表明每一個物品體積,w[]表明每一個物品價值
設f[i][j],表示前i件物品放入容量爲j的揹包的最大價值
所以可遍歷物品,並計算假設容量爲j時候的最大值。
此時有兩種狀況:
1.容量不夠(j < c[i]),則取不了當前物品,直接f[i][j]=f[i-1][j]
2.容量夠,則須要判斷取與不取當前物品的價值
若不取第i件,問題轉化爲求前i-1件物品放入容量爲v的揹包的問題,即f[i][j]=f[i-1][j]
若取第i件,問題轉化爲求前i-1件物品放入容量爲j-c[i]的揹包的問題,即f[i][j]=f[i-1][j-c[i]]+w[i]
因此f[i][j]便是求以上兩種狀況的最大值,最終狀態轉移方程是 f[i][v] = max(f[i-1][v], f[i-1][j-c[i]] + w[i])
最後答案就是f[n][v]數據

代碼實現

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int V = sc.nextInt();
        int[] v = new int[N + 1];
        int[] w = new int[N + 1];
        for(int i=1; i<=N; i++) {
            v[i] = sc.nextInt();
            w[i] = sc.nextInt();
        }

        System.out.println(cal(N, V, w, v));
    }

    /**
     * 求01揹包的解
     * @param n 物品個數
     * @param v 揹包總容量
     * @param w 每一個物品的價值,注意下標從1開始
     * @param c 每一個物品的體積,注意下標從1開始
     * @return
     */
    private static int cal(int n, int v, int[] w, int[] c) {
        /*
           
         */

        if (n == 0 || v == 0) return 0;
        if (w == null || w.length == 0) return 0;
        if (c == null || c.length == 0) return 0;


        int[][] f = new int[n + 1][v + 1];
        for(int i=1; i<=n; i++) {
            for(int j=1;j<=v;j++) {
                f[i][j] = j<c[i]? f[i-1][j] : Math.max(f[i-1][j], f[i-1][j-c[i]] + w[i]);
            }
        }

        return f[n][v];
    }
}
相關文章
相關標籤/搜索