01.题目及链接
题目链接:https://www.luogu.com.cn/problem/P1509
02.二维背包状态转移方程说明
有n件物品,两种不同的费用,选择这件物品必须同时付出这两种代价;对于每种代价都有一个可付出的最大值(背包容量)。问怎样选择物品可以得到最大的价值。这两种代价分别为代价1和代价2,第i件物品所需的两种代价分别为a[i]和 b[i]。两种代价可付出的最大值(两种背包容量)分别为V和U。物品的价值为w[i]。
状态转移方程
定义状态:dp[k][i][j]
背包两种容量分别为i,j的情况下,前k件物品可选择时物品的最大价值
dp[k][i][j]=Math.max(dp[k-1][i][j], dp[k-1][i-a[k]][j-b[k]]+w[k]) //a[k]<=i && b[k]<=j
dp[k][i][j]=dp[k-1][i][j]; //不满足条件:a[k]<=i && b[k]<=j
具体案例
for (int k = 1; k <= n; k++) //有n件物品
for (int i = 1; i <= V; i++) //背包最大容量V
for (int j = 1; j <= U; j++) { //背包最大容量U
if(i>=a[k]&&j>=b[k]) {
dp[k][i][j]=Math.max(dp[k-1][i][j], dp[k-1][i-a[k][j-b[k]+1);
}else {
dp[k][i][j]=dp[k-1][i][j];
}
}
状态压缩
dp[i][j]=Math.max(dp[i][j], dp[i-a[k][j-b[k]+w[k]) //逆向推导(从大到小)
具体案例
for (int k = 1; k <= n; k++)
for (int i = V; i >= a[k]; i--)
for (int j = U; j >= b[k]; j--)
dp[i][j] = dp[i - a[k][j - b[k]] + w[k];
03.解题思路
3.1解题思路
定义状态:
dp[i][j]
表示rmb为i,rp为j时能约到最多MM的数量dpTime[i][j]
表示rmb为i,rp为j时能约到最多MM的数量所需要的时间
状态转移:
dp[i][j]
dp[i][j] = dp[i - rmb[k]][j - rp[k]] + 1;
dpTime[i][j]
if (dp[i -rmb[k]][j - rp[k]] + 1 > dp[i][j]) {
dp[i][j] = dp[i - rmb[k]][j - rp[k]] + 1;
dpTime[i][j] = dpTime[i - rmb[k]][j - rp[k]] + time[k];
}
if ((dp[i][j] == dp[i - rmb[k]][j - rp[k]] + 1)
&& dpTime[i][j] > dpTime[i - rmb[k]][j - rp[k]] + time[k]) {
dpTime[i][j] = dpTime[i - rmb[k]][j - rp[k]] + time[k];
}
3.2具体代码
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[][] data = new int[n + 1][3];
for (int i = 1; i <= n; i++) {
data[i][0] = in.nextInt();// rmb
data[i][1] = in.nextInt();// rp
data[i][2] = in.nextInt();// time
}
int rmb = in.nextInt(), rp = in.nextInt();
//dp[i][j]表示rmb为i,rp为j时能约到最多MM的数量
int[][] dp = new int[rmb + 1][rp + 1];
//dpTime[i][j]表示rmb为i,rp为j时能约到最多MM的数量所需要的时间
int[][] dpTime = new int[rmb + 1][rp + 1];
for (int k = 1; k <= n; k++) {
for (int i = rmb; i >= data[k][0]; i--) {
for (int j = rp; j >= data[k][1]; j--) {
if (dp[i - data[k][0]][j - data[k][1]] + 1 > dp[i][j]) {
dp[i][j] = dp[i - data[k][0]][j - data[k][1]] + 1;
dpTime[i][j] = dpTime[i - data[k][0]][j - data[k][1]] + data[k][2];
}
if ((dp[i][j] == dp[i - data[k][0]][j - data[k][1]] + 1)
&& dpTime[i][j] > dpTime[i - data[k][0]][j - data[k][1]] + data[k][2]) {
dpTime[i][j] = dpTime[i - data[k][0]][j - data[k][1]] + data[k][2];
}
}
}
}
System.out.println(dpTime[rmb][rp]);
}
04.更多背包学习
https://blog.csdn.net/qq_46237746/article/details/123908504