题目 2721: 蓝桥杯2022年第十三届决赛真题-背包与魔法
- 原题链接:
- 完成情况:
- 解题思路:
- Problem Explanation
- Code Explanation
- Summary
- 参考代码:
- _题目2721_蓝桥杯2022年第十三届决赛真题_背包与魔法
- 错误经验吸取
原题链接:
题目 2721: 蓝桥杯2022年第十三届决赛真题-背包与魔法
https://www.dotcpp.com/oj/problem2721.html
完成情况:
解题思路:
The provided code solves a variant of the 0/1 knapsack problem with an additional magical transformation capability for one item. Here’s a detailed breakdown of the code and its workings:
Problem Explanation
You are given ( N ) items, each with a weight ( W_i ) and value ( V_i ). You also have a knapsack that can carry up to ( M ) weight. The goal is to maximize the total value of the items in the knapsack. Additionally, you can apply a magic transformation to one item which increases its weight by ( K ) and doubles its value.
Code Explanation
-
Input Parsing:
Scanner scanner = new Scanner(System.in); N = scanner.nextInt(); M = scanner.nextInt(); K = scanner.nextInt(); weights = new int[N + 1]; values = new int[N + 1]; dp_bagAndMagic = new int[M + K + 1][2]; for (int i = 1; i <= N; i++) {weights[i] = scanner.nextInt();values[i] = scanner.nextInt(); }
N
: Number of items.M
: Maximum weight the knapsack can carry.K
: Additional weight added when magic is used.- Arrays
weights
andvalues
store the weights and values of the items, respectively, starting from index 1. dp_bagAndMagic
is a 2D array where:dp_bagAndMagic[j][0]
represents the maximum value achievable with weightj
without using magic.dp_bagAndMagic[j][1]
represents the maximum value achievable with weightj
using magic on one item.
-
Dynamic Programming Table Update:
for (int i = 1; i <= N; i++) { // Iterate over itemsfor (int j = M; j >= weights[i]; j--) { // Iterate over possible weights from M down to the weight of the itemif (j >= weights[i] + K) { // If the current weight allows the use of magicdp_bagAndMagic[j][0] = Math.max(dp_bagAndMagic[j][0], dp_bagAndMagic[j - weights[i]][0] + values[i]);dp_bagAndMagic[j][1] = Math.max(dp_bagAndMagic[j][1], Math.max(dp_bagAndMagic[j - weights[i] - K][0] + 2 * values[i], dp_bagAndMagic[j - weights[i]][1] + values[i]));} else {dp_bagAndMagic[j][0] = Math.max(dp_bagAndMagic[j][0], dp_bagAndMagic[j - weights[i]][0] + values[i]);}} }
- The outer loop iterates over each item.
- The inner loop iterates over possible weights in reverse to avoid overwriting values prematurely.
- If the weight
j
can accommodate the item with the magic transformation (j >= weights[i] + K
), the code updates bothdp_bagAndMagic[j][0]
anddp_bagAndMagic[j][1]
.dp_bagAndMagic[j][0]
is updated considering the item without magic.dp_bagAndMagic[j][1]
is updated considering both using magic on the current item and the best possible value without magic.
- If the weight
j
cannot accommodate the magic transformation, onlydp_bagAndMagic[j][0]
is updated.
-
Determine Maximum Value:
int sum = 0; for (int i = 0; i <= M; i++) {sum = Math.max(sum, Math.max(dp_bagAndMagic[i][1], dp_bagAndMagic[i][0])); } System.out.println(sum);
- Iterate over all possible weights up to
M
to find the maximum value obtainable. sum
keeps track of the highest value found between using and not using magic.
- Iterate over all possible weights up to
Summary
- The code effectively handles the additional complexity introduced by the magical transformation by maintaining a dual-state DP table.
- It ensures the maximum possible value is calculated by considering both the scenarios of using and not using the magic for each weight and item.
- The final maximum value is derived by iterating over all possible weights, considering both states (with and without magic).
This approach ensures an optimal solution to the given problem using dynamic programming.
参考代码:
_题目2721_蓝桥杯2022年第十三届决赛真题_背包与魔法
package leetcode板块;import java.util.Scanner;public class _题目2721_蓝桥杯2022年第十三届决赛真题_背包与魔法 {private static int N,M,K;private static int weights [],values[];private static int dp_bagAndMagic [][];/**** @param args*/public static void main(String[] args) {// N件物品,第i件重量为W_i , 价值为 V_i ,最大承重是 M// 求最大价值// 小蓝还有【一个】模型,可以 让某个物品 重量+K,,价值变成 V_i * V_iScanner scanner = new Scanner(System.in);N = scanner.nextInt();M = scanner.nextInt();K = scanner.nextInt();// 数组额外加一个0号单元格,用于表示没选取物品,及其价值情况weights = new int[N+1];values = new int[N+1];dp_bagAndMagic = new int[M+K+1][2];for (int i = 1;i<=N;i++){weights[i] = scanner.nextInt();values[i] = scanner.nextInt();}// ---------- TODO dp迭代for (int i = 1;i<=N;i++){ // 物品件for (int j = M;j>=weights[i];j--){ //重量if (j>=weights[i] + K){ // 如果当前商品重量可以使用魔法// 进行考量dp_bagAndMagic[j][0] = Math.max(dp_bagAndMagic[j][0],dp_bagAndMagic[j-weights[i]][0] +values[i]);dp_bagAndMagic[j][1] = Math.max(dp_bagAndMagic[j][1],Math.max(dp_bagAndMagic[j-weights[i]-K][0] + 2*values[i],dp_bagAndMagic[j-weights[i]][1]+values[i]));}else{dp_bagAndMagic[j][0] = Math.max(dp_bagAndMagic[j][0],dp_bagAndMagic[j-weights[i]][0] + values[i]);}}}int sum = 0;for (int i = 0;i<=M;i++){sum = Math.max(sum,Math.max(dp_bagAndMagic[i][1],dp_bagAndMagic[i][0]));}System.out.println(sum);}
}