题目链接:题目页面
小明是一位科学家,他需要参加一场重要的国际科学大会,以展示自己的最新研究成果。他需要带一些研究材料,但是他的行李箱空间有限。这些研究材料包括实验设备、文献资料和实验样本等等,它们各自占据不同的空间,并且具有不同的价值。
小明的行李空间为 N,问小明应该如何抉择,才能携带最大价值的研究材料,每种研究材料只能选择一次,并且只有选与不选两种选择,不能进行切割。
输入描述
第一行包含两个正整数,第一个整数 M 代表研究材料的
种类,第二个正整数 N,代表小明的行李空间。
第二行包含 M 个正整数,代表每种研究材料的所占空间。
第三行包含 M 个正整数,代表每种研究材料的价值。
输出描述
输出一个整数,代表小明能够携带的研究材料的最大价值。
输入示例
6 1 2 2 3 1 5 2 2 3 1 5 4 3
输出示例
5
提示信息
小明能够携带 6 种研究材料,但是行李空间只有 1,而占用空间为 1 的研究材料价值为 5,所以最终答案输出 5。
数据范围:
1 <= N <= 1000
1 <= M <= 1000
研究材料占用空间和价值都小于等于 1000
其实针对背包问题,做了几个题目后发现,都可以直接套用模板了,但是我们还是需要明白它是怎么实现的,不能一知半解。
我们需要明白的其实有:
1、dp[i]指的是什么?
2、dp数组初始值应该是哪些,为什么?
3、递归公式是怎样的,为什么是这样的?
4、weight数组是哪个,value数组是哪个?最大容量是多少?
具体思路:
这里简单画了一个图。
1、我们可以知道的是dp[i]是当为第i个物品的时候。
2、dp数组初始化要的是先把物品1的数组全部赋值
3、dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-weight[i]] + value[i])
就是当前j容量的时候,可以加入第i个物品时候的最大价值
这里是针对上面题目给出的代码:
import java.util.*;public class Main {public static void main(String[] args) {// 背包容量 N// 物品种类 MScanner sc = new Scanner(System.in);int M = sc.nextInt();int N = sc.nextInt();int[] values = new int[M];int[] weights = 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 = 0; j <= N; j++) {if(weights[i] > j) {dp[i][j] = dp[i-1][j];} else {dp[i][j] = Math.max(dp[i-1][j],dp[i-1][j-weights[i]] + values[i]);}}}System.out.println(dp[M-1][N]);}
}