AcWing 9. 分组背包问题【Java】——二维dp表示
原题链接
中等
作者:
赤赤之龙
,
2020-02-29 18:19:20
,
所有人可见
,
阅读 2464
/*
本解法主要用来描述二维dp的记录,在每一次遍历分组时,使用临时变量来记录最大值,而非直接覆盖
当然,复杂度比一维dp有所增加,此解法主要用来解决为什么不能直接使用以下公式的疑惑
dp[i][j] = Math.max(dp[i - 1][j],dp[i - 1][j - v] + w);
*/
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
int MAX = 101;
int N = input.nextInt();
int V = input.nextInt();
int[][] vol = new int[MAX][MAX];
int[][] val = new int[MAX][MAX];
for(int i = 1; i < N + 1; i++){
int num = input.nextInt();
for(int j = 1; j < num + 1; j++){
vol[i][j] = input.nextInt();
val[i][j] = input.nextInt();
}
}
input.close();
int[][] dp = new int[N + 1][V + 1];
for(int i = 1; i < N + 1; i++){
for(int j = 1; j < V + 1; j++){
// tmpMax用来记录该分组内本次循环的最大值,如果不设置该值,
// 则会导致每次循环记录的是大于dp[i - 1][j]的最后一个满足条件的k的值,而不是最值
int tmpMax = 0;
// vol[i][k] != 0的目的是提前退出循环,因为给定的数组vo[][]是定长的,而有效的输入并不一定填满整个数组
// 如果使用List<List<Integer>>,则可以直接使用.length()来作为循环的退出条件
for(int k = 1; k < MAX && vol[i][k] != 0; k++){
if(j >= vol[i][k]){
dp[i][j] = Math.max(dp[i - 1][j],dp[i - 1][j - vol[i][k]] + val[i][k]);
tmpMax = tmpMax > dp[i][j]?tmpMax:dp[i][j];
}else{
dp[i][j] = dp[i - 1][j];
}
}
dp[i][j] = tmpMax > dp[i][j]?tmpMax:dp[i][j];
}
}
System.out.println(dp[N][V]);
}
}
for( int i=1; i<=n; i )
{
for( int k=1; k<=m; k )
{
f[i][k] = f[i-1][k];
for( int j=1; j<=s[i]; j++ )
{
if(k>=v[i][j]) f[i][k] = max(f[i][k], f[i-1][k-v[i][j]]+w[i][j]);
}
}
}
这样就不用拿tmpMax存了
强强强