import java.util.*;
/**
* NC309 完全背包
* @author d3y1
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param v int整型
* @param n int整型
* @param nums int整型ArrayList<ArrayList<>>
* @return int整型ArrayList
*/
public ArrayList<Integer> knapsack (int v, int n, ArrayList<ArrayList<Integer>> nums) {
// return solution1(v, n, nums);
return solution2(v, n, nums);
}
/**
* 动态规划
*
* dp[i]表示背包体积为i时的最大价值
*
* 1. 背包能装物品的最大价值
* dp[i] = Math.max(dp[i], dp[i-volume]+wealth) , i>=volume
*
* 2. 背包能装物品的最大价值(背包恰好装满)
* { Math.max(dp[i], wealth) , i=volume
* dp[i] = {
* { Math.max(dp[i], dp[i-volume]+wealth) , i>volume && dp[i-volume]>0
*
* @param v
* @param n
* @param nums
* @return
*/
private ArrayList<Integer> solution1(int v, int n, ArrayList<ArrayList<Integer>> nums){
ArrayList<Integer> result = new ArrayList<Integer>();
int[] dp = new int[v+1];
int volume,wealth;
// 1. 背包能装物品的最大价值
for(int i=1; i<=v; i++){
for(int j=0; j<n; j++){
volume = nums.get(j).get(0);
wealth = nums.get(j).get(1);
if(i >= volume){
dp[i] = Math.max(dp[i], dp[i-volume]+wealth);
}
}
}
result.add(dp[v]);
// 2. 背包能装物品的最大价值(背包恰好装满)
Arrays.fill(dp, 0);
for(int i=1; i<=v; i++){
for(int j=0; j<n; j++){
volume = nums.get(j).get(0);
wealth = nums.get(j).get(1);
if(i == volume){
dp[i] = Math.max(dp[i], wealth);
}
if(i > volume){
// i-volume能装满
if(dp[i-volume] > 0){
dp[i] = Math.max(dp[i], dp[i-volume]+wealth);
}
}
}
}
result.add(dp[v]);
return result;
}
/**
* 动态规划
*
* dp[i][0]表示背包体积为i时的最大价值
* dp[i][1]表示背包体积为i时的最大价值(背包恰好装满)
*
* 1. 背包能装物品的最大价值
* dp[i][0] = Math.max(dp[i][0], dp[i-volume][0]+wealth) , i>=volume
*
* 2. 背包能装物品的最大价值(背包恰好装满)
* { Math.max(dp[i][1], wealth) , i=volume
* dp[i][1] = {
* { Math.max(dp[i][1], dp[i-volume][1]+wealth) , i>volume && dp[i-volume][1]>0
*
* @param v
* @param n
* @param nums
* @return
*/
private ArrayList<Integer> solution2(int v, int n, ArrayList<ArrayList<Integer>> nums){
ArrayList<Integer> result = new ArrayList<Integer>();
int[][] dp = new int[v+1][2];
int volume,wealth;
// 1. 背包能装物品的最大价值 dp[i][0]
// 2. 背包能装物品的最大价值(背包恰好装满) dp[i][1]
for(int i=1; i<=v; i++){
for(int j=0; j<n; j++){
volume = nums.get(j).get(0);
wealth = nums.get(j).get(1);
if(i == volume){
dp[i][0] = Math.max(dp[i][0], dp[i-volume][0]+wealth);
dp[i][1] = Math.max(dp[i][1], wealth);
}
if(i > volume){
dp[i][0] = Math.max(dp[i][0], dp[i-volume][0]+wealth);
// i-volume能装满
if(dp[i-volume][1] > 0){
dp[i][1] = Math.max(dp[i][1], dp[i-volume][1]+wealth);
}
}
}
}
result.add(dp[v][0]);
result.add(dp[v][1]);
return result;
}
}