动态规划 - 背包专题

63 阅读1分钟

AcWing 2. 01背包问题

  • 思路 : 闫氏DP分析法

image.png

  • 代码实现 【二维】
import java.util.*;
import java.io.*;
public class Main {

    static int[] v;
    static int[] w;
    static int[][] f;
    public static void main(String[] args) {
        Scanner sc = new Scanner(new BufferedInputStream(System.in));
        int n = sc.nextInt();
        int m = sc.nextInt();
        v = new int[n + 1];
        w = new int[n + 1];
        f = new int[n + 1][m + 1];

        for (int i = 1 ; i <= n ; i ++) {
            v[i] = sc.nextInt();
            w[i] = sc.nextInt();
        }

        for (int i = 1 ; i <= n ; i ++) {
            for (int j = 0 ; j <= m ; j ++)
                if (j >= v[i])
                    f[i][j] = Math.max(f[i - 1] [j - v[i]] + w[i] , f[i - 1][j]);
                else  f[i][j] = f[i - 1][j];
        }

        System.out.println(f[n][m]);
    }
}

  • 优化 : 方程决策 f[i][j] = Math.max(f[i -1][j] , f[i - 1][j - v[i]] + w[i]);
  • i 层 都是由 i - 1 层 推导而来。这时候就可以用 滚动数组 技巧.
  • 本层状态由 上层 状态得到的话 需要从大到小枚举。
import java.util.*;
import java.io.*;
public class Main {

    static int[] v;
    static int[] w;
    static int[] f;
    public static void main(String[] args) {
        Scanner sc = new Scanner(new BufferedInputStream(System.in));
        int n = sc.nextInt();
        int m = sc.nextInt();
        v = new int[n + 1];
        w = new int[n + 1];
        f = new int[m + 1];

        for (int i = 1 ; i <= n ; i ++) {
            v[i] = sc.nextInt();
            w[i] = sc.nextInt();
        }

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

        System.out.println(f[m]);
    }
}

AcWing 3. 完全背包问题

image.png

  • 思路 : 闫氏 dp 分析法

image.png

  • 代码
import java.util.*;
public class Main {
    static int n ;
    static int m;
    static int[] v;
    static int[] w;
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        v = new int[n + 1];
        w = new int[n + 1];
        for (int i = 1; i <= n ; i ++ ) {
            v[i] = sc.nextInt();
            w[i] = sc.nextInt();
        }
        
        int[][] dp = new int[n + 1][m + 1];
        for (int i =  1; i <= n ; i ++ ){
            for (int j = 0; j <= m; j ++) {
                for (int k = 0 ; k * v[i] <= j ; k ++) 
                    dp[i][j] = Math.max(dp[i][j],dp[i-1][j - k * v[i]]  + k * w[i]); 
            }
        }
        System.out.println(dp[n][m]);
    }
}
  • 优化 :
import java.util.*;
public class Main {
    static int n ;
    static int m;
    static int[] v;
    static int[] w;
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        v = new int[n + 1];
        w = new int[n + 1];
        for (int i = 1; i <= n ; i ++ ) {
            v[i] = sc.nextInt();
            w[i] = sc.nextInt();
        }
        
        int[] dp = new int[m + 1];
        for (int i =  1; i <= n ; i ++ ){
            for (int j = v[i]; j <= m; j ++) {
                dp[j] = Math.max(dp[j],dp[j - v[i]] + w[i]); 
            }
        }
        System.out.println(dp[m]);
    }
}