01.题目
02.解题思路
2.1完全背包介绍及状态转移方程
完全背包简介
有 N 种物品和一个容量是 V 的背包,每种物品都有无限件可用。第 i 种物品的重量是 wi 、价值是 vi。求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。输出最大价值。( values 是价值数组,weights 是重量数组)
基于0-1背包解完全背包
for (int i = 1; i <=values.length; i++) {//i表示前i个物品
for (int j = capacity; j >=weights[i-1]; j--) {
//从右到左进行覆盖,当j < weights[i-1],证明第i件物品不能选
for (int k = 0; k <= j/weights[i]; k++) {
dp[j]=Math.max(dp[j], dp[j-k*weights[i-1]]+k*values[i-1]);
}
}
}
完全背包状态转态移方程
定义状态:dp(i, j) 是最大承重为 j、有前 i 件物品可选时的最大总价值
则其状态转移方程为:dp[i][j]=Math.max( dp[i][j], dp[i][j-weights[i]]+values[i] )
状态压缩
dp(j) = max { dp(j), dp(j – weights[i – 1]) + values[i – 1] } 注意(要从小到大递推)
2.2解题思路
以数据2为例子,对数据进行处理可构造出下图数组
3 3 100
10 20 15
15 17 13
15 25 16
数组说明:weights数组:[10, 20, 15] 表示第1天买入3个纪念品所需要的钱(单个)
valuess数组:[5, -3, -2] 表示第2天买出3个纪念品所获得的钱(单个)
2.3具体代码
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
//分别代表未来天数 T,纪念品数量 N,小伟现在拥有的金币数量M
int T=in.nextInt(),N=in.nextInt(),M=in.nextInt();
int[][] data=new int[T+1][N+1];//重量数组
int[][] incom=new int[T+1][N+1];//价值数组
for (int i = 1; i <= T; i++) {
for (int j = 1; j <=N; j++) {
data[i][j]=in.nextInt();//输入数据
incom[i-1][j]=data[i][j]-data[i-1][j];//根据输入数据构造价值数组
}
}
int[] dp=new int[10000];
for (int t = 1; t < T; t++) {
M+=dp[M];//修改最大本金
dp=new int[10000];//重新初始化状态数组
//根据状态转移方程推导
for (int i = 1; i <= N; i++) {
for (int j = data[t][i]; j <= M; j++) {
dp[j]=Math.max(dp[j], dp[j-data[t][i]]+incom[t][i]);
}
}
}
System.out.println(dp[M]+M);
}
03.更多背包学习
https://blog.csdn.net/qq_46237746/article/details/123908504