1.01背包
1.1 题目描述
小明是一位科学家,他需要参加一场重要的国际科学大会,以展示自己的最新研究成果。他需要带一些研究材料,但是他的行李箱空间有限。这些研究材料包括实验设备、文献资料和实验样本等等,它们各自占据不同的空间,并且具有不同的价值。
小明的行李空间为 N,问小明应该如何抉择,才能携带最大价值的研究材料,每种研究材料只能选择一次,并且只有选与不选两种选择,不能进行切割。
输入描述
第一行包含两个正整数,第一个整数 M 代表研究材料的种类,第二个正整数 N,代表小明的行李空间。
第二行包含 M 个正整数,代表每种研究材料的所占空间。
第三行包含 M 个正整数,代表每种研究材料的价值。
输出描述
输出一个整数,代表小明能够携带的研究材料的最大价值。
输入示例
1 2 3
| 6 1 2 2 3 1 5 2 2 3 1 5 4 3
|
输出示例
提示信息
小明能够携带 6 种研究材料,但是行李空间只有 1,而占用空间为 1 的研究材料价值为 5,所以最终答案输出 5。
数据范围:
1 <= N <= 5000
1 <= M <= 5000
研究材料占用空间和价值都小于等于 1000
1.2 题解
1.2.1 动态规划
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| import java.util.Scanner;
public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in);
int m = sc.nextInt(); int n = sc.nextInt();
int[] weights = new int[m]; int[] values = new int[m];
for (int i = 0; i < m; i++) { weights[i] = sc.nextInt(); }
for (int i = 0; i < m; i++) { values[i] = sc.nextInt(); }
int[][] dp = new int[m][n + 1];
for (int i = weights[0]; i <= n; i++) { dp[0][i] = values[0]; }
for (int i = 1; i < m; i++) { for (int j = weights[i]; j <= n; j++) { dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weights[i]] + values[i]); } }
System.out.println(dp[m - 1][n]); } }
|
1.2.2 动态规划-滚动数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| import java.util.Scanner;
public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in);
int m = sc.nextInt(); int n = sc.nextInt();
int[] weights = new int[m]; int[] values = new int[m];
for (int i = 0; i < m; i++) { weights[i] = sc.nextInt(); }
for (int i = 0; i < m; i++) { values[i] = sc.nextInt(); }
int[] dp = new int[n + 1];
for (int i = weights[0]; i <= n; i++) { dp[i] = values[0]; }
for (int i = 1; i < m; i++) { for (int j = n; j >= weights[i]; j--) { dp[j] = Math.max(dp[j], dp[j - weights[i]] + values[i]); } }
System.out.println(dp[n]); } }
|
1.2.3 动态规划-滚动数组优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| import java.util.Scanner;
public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in);
int m = sc.nextInt(); int n = sc.nextInt();
int[] weights = new int[m]; int[] values = new int[m];
for (int i = 0; i < m; i++) { weights[i] = sc.nextInt(); }
for (int i = 0; i < m; i++) { values[i] = sc.nextInt(); }
int[] dp = new int[n + 1];
for (int i = 0; i < m; i++) { for (int j = n; j >= weights[i]; j--) { dp[j] = Math.max(dp[j], dp[j - weights[i]] + values[i]); } }
System.out.println(dp[n]);
sc.close(); } }
|
2.完全背包
2.1 题目描述
小明是一位科学家,他需要参加一场重要的国际科学大会,以展示自己的最新研究成果。他需要带一些研究材料,但是他的行李箱空间有限。这些研究材料包括实验设备、文献资料和实验样本等等,它们各自占据不同的重量,并且具有不同的价值。
小明的行李箱所能承担的总重量为 N,问小明应该如何抉择,才能携带最大价值的研究材料,每种研究材料可以选择无数次,并且可以重复选择。
输入描述
第一行包含两个整数,N,V,分别表示研究材料的种类和行李空间
接下来包含 N 行,每行两个整数 wi 和 vi,代表第 i 种研究材料的重量和价值
输出描述
输出一个整数,表示最大价值。
输入示例
输出示例
提示信息
第一种材料选择五次,可以达到最大值。
数据范围:
1 <= N <= 10000;
1 <= V <= 10000;
1 <= wi, vi <= 10^9.
2.2 题解
2.2.1 滚动数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| 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[] weights = new int[n]; int[] values = new int[n];
for (int i = 0; i < n; i++) { weights[i] = sc.nextInt(); values[i] = sc.nextInt(); }
int[] dp = new int[v + 1];
for (int i = 0; i < n; i++) { for (int j = v; j >= weights[i]; j--) { dp[j] = Math.max(dp[j], dp[j - weights[i]] + values[i]); } }
System.out.println(dp[v]); } }
|
3.多重背包
3.1 题目描述
你是一名宇航员,即将前往一个遥远的行星。在这个行星上,有许多不同类型的矿石资源,每种矿石都有不同的重要性和价值。你需要选择哪些矿石带回地球,但你的宇航舱有一定的容量限制。
给定一个宇航舱,最大容量为 C。现在有 N 种不同类型的矿石,每种矿石有一个重量 w[i],一个价值 v[i],以及最多 k[i] 个可用。不同类型的矿石在地球上的市场价值不同。你需要计算如何在不超过宇航舱容量的情况下,最大化你所能获取的总价值。
输入描述
输入共包括四行,第一行包含两个整数 C 和 N,分别表示宇航舱的容量和矿石的种类数量。
接下来的三行,每行包含 N 个正整数。具体如下:
第二行包含 N 个整数,表示 N 种矿石的重量。
第三行包含 N 个整数,表示 N 种矿石的价格。
第四行包含 N 个整数,表示 N 种矿石的可用数量上限。
输出描述
输出一个整数,代表获取的最大价值。
输入示例
1 2 3 4
| 10 3 1 3 4 15 20 30 2 3 2
|
输出示例
提示信息
数据范围:
1 <= C <= 10000;
1 <= N <= 10000;
1 <= w[i], v[i], k[i] <= 10000;
3.2 题解
3.2.1 转化成01背包-滚动数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| import java.util.Scanner;
public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int c = sc.nextInt(); int n = sc.nextInt();
int[] w = new int[n]; int[] v = new int[n]; int[] k = new int[n];
for (int i = 0; i < n; i++) { w[i] = sc.nextInt(); }
for (int i = 0; i < n; i++) { v[i] = sc.nextInt(); }
for (int i = 0; i < n; i++) { k[i] = sc.nextInt(); }
int[] dp = new int[c + 1];
for (int i = 0; i < n; i++) { for (int j = c; j >= w[i]; j--) { for (int m = 1; m <= k[i] && (j - m * w[i]) >= 0; m++) { dp[j] = Math.max(dp[j], dp[j - m * w[i]] + m * v[i]); } } }
System.out.println(dp[c]); } }
|