背包问题_13.pdf

问题描述

有 N 种物品和一个容量是 V 的背包。
物品一共有三类:

  • 第一类物品只能用1次(01背包);
  • 第二类物品可以用无限次(完全背包);
  • 第三类物品最多只能用 si 次(多重背包);

每种体积是 vi,价值是 wi。
求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。
输入格式
第一行两个整数,N,VN,V,用空格隔开,分别表示物品种数和背包容积。
接下来有 N 行,每行三个整数 vi,wi,si,用空格隔开,分别表示第 i 种物品的体积、价值和数量。

  • si=−1 表示第 i 种物品只能用1次;
  • si=0 表示第 i 种物品可以用无限次;
  • si>0 表示第 i 种物品可以使用 si 次;

输出格式
输出一个整数,表示最大价值。
数据范围
00−1≤si≤1000
输入样例
4 5
1 2 -1
2 4 1
3 4 0
4 5 2
输出样例:
8

思路:
将01,完全,多重背包组合起来即可。

二维版本

  1. import java.util.*;
  2. public class Main {
  3. static final int N = 1010;
  4. static int[][] f = new int[N][N];
  5. static int n, m;
  6. public static void main(String[] args) {
  7. Scanner sc = new Scanner(System.in);
  8. n = sc.nextInt();
  9. m = sc.nextInt();
  10. for (int i = 1; i <= n; i++) {
  11. int v = sc.nextInt(), w = sc.nextInt(), s = sc.nextInt();
  12. if (s == 0) {
  13. for (int j = 0; j <= m; j++) {
  14. f[i][j] = f[i - 1][j];
  15. if (j >= v)
  16. f[i][j] = Math.max(f[i][j], f[i][j - v] + w);
  17. }
  18. } else {
  19. if (s == -1) s = 1;
  20. // 不选
  21. for (int j = 0; j <= m; j++)
  22. f[i][j] = f[i - 1][j];
  23. // 选
  24. for (int k = 1; k <= s; k <<= 1) {
  25. for (int j = m; j >= k * v; j--) {
  26. f[i][j] = Math.max(f[i][j], f[i][j - k * v] + w * k);
  27. }
  28. s -= k;
  29. }
  30. if (s > 0) {
  31. for (int j = m; j >= s * v; j--) {
  32. f[i][j] = Math.max(f[i][j], f[i][j - s * v] + w * s);
  33. }
  34. }
  35. }
  36. }
  37. System.out.println(f[n][m]);
  38. }
  39. }

一维版本

  1. import java.util.*;
  2. public class Main {
  3. static final int N = 1010;
  4. static int[] f = new int[N];
  5. static int n, m;
  6. public static void main(String[] args) {
  7. Scanner sc = new Scanner(System.in);
  8. n = sc.nextInt();
  9. m = sc.nextInt();
  10. for (int i = 1; i <= n; i++) {
  11. int v = sc.nextInt(), w = sc.nextInt(), s = sc.nextInt();
  12. if (s == 0) {
  13. for (int j = v; j <= m; j++)
  14. f[j] = Math.max(f[j], f[j - v] + w);
  15. } else {
  16. if (s == -1) s = 1;
  17. for (int k = 1; k <= s; k <<= 1) {
  18. for (int j = m; j >= k * v; j--)
  19. f[j] = Math.max(f[j], f[j - k * v] + k * w);
  20. s -= k;
  21. }
  22. if (s > 0)
  23. for (int j = m; j >= s * v; j--)
  24. f[j] = Math.max(f[j], f[j - s * v] + s * w);
  25. }
  26. }
  27. System.out.println(f[m]);
  28. }
  29. }