问题描述
有 n 种(每一种有无数个)重量和价值分别为Wi,Vi的物品,现从这些物品中挑选出总
量不超过 W 的物品,求所有方案中价值总和的最大值。
输入
输入包含多组测试用例,每一例的开头为两位整数 n、W(1<=n<=10000,1<=W<=1000)
,接下来有 n 行,每一行有两位整数 Wi、Vi(1<=Wi<=10000,1<=Vi<=100)
输出
输出为一行,即所有方案中价值总和的最大值
样例输入
3 4
1 2
2 5
3 7
3 5
2 3
3 4
4 5
样例输出
10
7
使用二维数组的题解:
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
int n = sc.nextInt();
int m = sc.nextInt();
int[][] dp = new int[n+1][m+1];
for(int i=1;i<=n;i++){
int w = sc.nextInt();
int v = sc.nextInt();
for(int j=1;j<=m;j++){ // 关键在于从背包可容纳的最大体积开始递减
if(j>=w){
// 如果实在理解不了建议重新理解最基础的01背包,然后再尝试理解01背包的变形
dp[i][j] = max(dp[i-1][j],max(dp[i-1][j-w]+v,dp[i][j-w]+dp[i][w]));
} else {
dp[i][j]=dp[i-1][j];
}
}
}
// for(int i=1;i<=n;i++){ // 打印动态规划数组,便于debug和理解算法流程
// for(int j=1;j<=m;j++){
// System.out.print(dp[i][j]+" ");
// }
// System.out.println();
// }
if(dp[n][m]!=0)
System.out.println(dp[n][m]);
else
System.out.println("-1");
}
}
private static int max(int a, int b) {
if(a<b)
return b;
return a;
}
}
使用一维数组的题解:
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
int n = sc.nextInt();
int m = sc.nextInt();
int[] dp = new int[m+1];
for(int i=1;i<=n;i++){
int w = sc.nextInt();
int v = sc.nextInt();
for(int j=1;j<=m;j++){ // 关键在于从背包可容纳的最大体积开始递减
if(j>=w){
// 如果实在理解不了建议重新理解最基础的01背包,然后再尝试理解01背包的变形
dp[j] = max(dp[j],max(dp[j-w]+v,dp[j-w]+dp[w]));
}
}
}
// for(int i=1;i<=n;i++){ // 打印动态规划数组,便于debug和理解算法流程
// for(int j=1;j<=m;j++){
// System.out.print(dp[i][j]+" ");
// }
// System.out.println();
// }
if(dp[m]!=0)
System.out.println(dp[m]);
else
System.out.println("-1");
}
}
private static int max(int a, int b) {
if(a<b)
return b;
return a;
}
}
动态规划真的好费脑啊,脑壳痛,加油吧!