思路:背包问题
首先不考虑使用魔法的情况,就是单纯地背包问题。唯一不同的就是使用魔法可以让你所拿的物品中的一个物品的价值翻倍。所以你需要记录每一步中拿到的单个商品的最大值,用于后面确定加倍的是最大价值。
AC代码:
import java.io.*;
import java.util.Arrays;
public class Main{
public static void main(String[] args) throws IOException {
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
int N,M,K;
in.nextToken();N=(int)in.nval;
in.nextToken();M=(int)in.nval;
in.nextToken();K=(int)in.nval;
int[] weight = new int[N+1];
int[] values = new int[N+1];
int[][] dp = new int[N+1][M+1];
//选择在有前i种物品时,容量为j时 背包中单个商品的最大价值 这个是用来后期使用魔法加倍的
int[][] max = new int[N+1][M+1];
for (int i = 1; i <= N; i++) {
in.nextToken();int wei = (int) in.nval; weight[i]= wei;
in.nextToken();int val = (int) in.nval; values[i] = val;
}
int t1,t2;
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= M; j++) {
//这么长串的判断就是为了记录max[][]
if(j-weight[i]<0){
if(dp[i-1][j]>dp[i][j-1]){
max[i][j] = max[i-1][j];
dp[i][j] = dp[i-1][j];
}else {
max[i][j] = max[i][j-1];
dp[i][j] = dp[i][j-1];
}
}else {
if(dp[i-1][j]>dp[i][j-1]){
t1=dp[i-1][j];
t2=max[i-1][j];
}else if(dp[i-1][j] == dp[i][j-1] ){
t1=dp[i-1][j];
t2 = Math.max(max[i-1][j],max[i][j-1]);
}else{
t1=dp[i][j-1];
t2=max[i][j-1];
}
if(t1<dp[i-1][j-weight[i]]+values[i]){
dp[i][j] = dp[i-1][j-weight[i]]+values[i];
max[i][j] = Math.max(max[i-1][j-weight[i]],values[i]);
}else if(t1 == dp[i-1][j-weight[i]]+values[i]){
dp[i][j] = t1;
max[i][j] = Math.max(t2,Math.max(max[i-1][j-weight[i]],values[i]));
}else {
dp[i][j] = t1;
max[i][j] = t2;
}
}
}
}
int res = dp[N][M];
res = Math.max(res,dp[N][M-K]+max[N][M-K]);
System.out.println(res);
}
}