01.题目及链接
题目链接:https://www.luogu.com.cn/problem/P6771
02.多重背包状态转移方程说明
了解多重背包
有 N 种物品和一个容量是 V 的背包,每种物品都有n[i]可用。第 i 种物品的重量是 w[i] 、价值是 v[i]。求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。输出最大价值。
状态转移方程
定义状态dp[i]:背包两种容量分别为j的情况下,物品的最大价值
for (int i = 1; i <= n; i++) //有N种物品
for (int j = v; j>=0; j--) //容量v
for (int k = 1; k <= n[i]; k++) //第i个物品的数量为n[i]
if(j>=k*w[i]) dp[j]=Math.max(dp[j], dp[j-k*w[i]]+k*v[i]);
或
for (int i = 1; i <= n; i++) //有N种物品
for (int k = 1; k <= n[i]; k++) //第i个物品的数量为n[i]
for (int j = v; j >= w[i]; j--) //容量v
dp[j]=Math.max(dp[j], dp[j-w[i]]+v[i]);
03.具体代码
解题思路:
- 根据限制进行排序(从小到大)
- 根据状态转移方程进行DP
DP写法1
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
int n=in.nextInt();
int[][] input=new int[n+1][3];
int maxLimit=0;//最大限制
for (int i = 1; i <= n; i++) {
input[i][0]=in.nextInt();//高度
input[i][1]=in.nextInt();//限制
input[i][2]=in.nextInt();//数量
maxLimit=Math.max(maxLimit, input[i][1]);
}
Arrays.sort(input,(o1,o2)->o1[1]-o2[1]);//根据限制进行排序(从小到大)
int max=0;
int[] dp=new int[maxLimit+1];
for (int i = 1; i <= n; i++) {
for (int k = 1; k <= input[i][2]; k++) {
for (int j = input[i][1]; j >= input[i][0]; j--) {
dp[j]=Math.max(dp[j], dp[j-input[i][0]]+input[i][0]);
max=Math.max(dp[j], max);
}
}
}
System.out.println(max);
}
DP写法2
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
int n=in.nextInt();
int[][] input=new int[n+1][3];
int maxLimit=0;
for (int i = 1; i <= n; i++) {
input[i][0]=in.nextInt();//高度
input[i][1]=in.nextInt();//限制
input[i][2]=in.nextInt();//数量
maxLimit=Math.max(maxLimit, input[i][1]);
}
Arrays.sort(input,(o1,o2)->o1[1]-o2[1]);
int max=0;
int[] dp=new int[maxLimit+1];
for (int i = 1; i <= n; i++) {
for (int j = input[i][1]; j >= 0; j--) {
for (int k = 1; k <= input[i][2]; k++) {
if(j>=k*input[i][0]) {
dp[j]=Math.max(dp[j], dp[j-k*input[i][0]]+k*input[i][0]);
max=Math.max(dp[j], max);
}
}
}
}
System.out.println(max);
}
04.更多背包学习
https://blog.csdn.net/qq_46237746/article/details/123908504