题解 | #购物单# (代码逐行解释)
购物单
https://www.nowcoder.com/practice/f9c6f980eeec43ef85be20755ddbeaf4
import java.util.Scanner;
/**
01背包:dp[i][j]表示前i件物品,背包容量为j能够取得的最大价值
1.定义状态
附件不能独立存在,因此主件就是总的物件数量
附件情况分为以下四种:
主件 0
主件+附件1 1
主件+附件2 2
主件+附件1+附件2 3
用w[i][k]表示主件i且取k(0-3)种情况附件对应的价格
用v[i][k]表示主件i且取k种情况附件对应的重要度
2.转移方程:
现在就转为01背包问题了
dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i][k]]+v[i][k])
时间:O(n)
空间:O(n^2)
*/
/*
1000 5
800 2 0
400 5 1
300 5 1
400 3 0
500 2 0
2200
50 5
20 3 5
20 3 5
10 3 0
10 2 0
10 1 0
130
*/
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 数据处理,转为目标数据结构
int N = in.nextInt(), m = in.nextInt();
int cnt = 0; // 主件数量
int[][] arr = new int[m][3];
for (int i = 0; i < m; i++) {
for (int j = 0; j < 3; j++) {
arr[i][j]=in.nextInt();
}
if (arr[i][2] == 0) {
cnt++;
}
}
int[][] w=new int[cnt][4], // 主件i和附件情况k的价格
v=new int[cnt][4]; // 主件i和附件情况的满意度
int i=0;
for(int j=0;j<m;j++){
if(arr[j][2]==0){ // 找到主件j
w[i][0]=arr[j][0]; // 对应附件情况0
v[i][0]=arr[j][0]*arr[j][1];
for(int l=0;l<m;l++){ // 找到其它附件情况
if(arr[l][2]==j+1){ // 为主件j对应的附件
if(w[i][1]==0){ // 说明是附件1
w[i][1]=w[i][0]+arr[l][0]; // 附件情况1
v[i][1]=v[i][0]+arr[l][0]*arr[l][1];
}else{
w[i][2]=w[i][0]+arr[l][0]; // 附件情况2
v[i][2]=v[i][0]+arr[l][0]*arr[l][1];
w[i][3]=w[i][1]+w[i][2]-w[i][0]; // 附件情况3
v[i][3]=v[i][1]+v[i][2]-v[i][0];
}
}
}
i++; // 下一个主件
}
}
// 套用01背包
int[][] dp=new int[cnt+1][N+1];// 前i件主件,容量为N的最大价值
int ans=0;
for(int j=1;j<=cnt;j++){
for(int t=0;t<=N;t++){
// 不取或附件0123
dp[j][t]=dp[j-1][t]; // 当前不取
for(int l=0;l<=3;l++){
if(t>=w[j-1][l]){
dp[j][t]=Math.max(dp[j][t],dp[j-1][t-w[j-1][l]]+v[j-1][l]); // 附件0123
}
}
}
ans=Math.max(ans,dp[j][N]);
}
System.out.println(ans);
}
}

美的集团公司福利 717人发布