题解(快来看)
2026-07-30 18:47:59
发布于:广东
一、问题分析
本题是一个典型的 0-1 背包问题。给定 n 件物品,每件物品只有 1 件,具有体积 v[i] 和价值 c[i]。背包的固定容量为 10,要求在不超过背包容量的前提下,选择若干物品使得总价值最大
约束条件:0 <= n <= 100,体积和价值均为整数。题目明确要求使用二维数组实现动态规划
二、算法思路
采用动态规划(Dynamic Programming)求解
状态定义
定义二维数组 dp[i][j],其中:
i 表示考虑前 i 件物品(从第 1 件到第 i 件);
j 表示当前背包的容量(取值范围为 0 到 10);
dp[i][j] 的值表示在前 i 件物品中选择,且背包容量为 j 时,能够获得的最大总价值
状态转移方程
对于第 i 件物品(体积 v[i],价值 c[i]),存在两种决策:
不选第 i 件物品:此时最大价值等于前 i-1 件物品在容量 j 下的最优解,即 dp[i-1][j]
选第 i 件物品:前提是当前容量 j 必须大于等于物品体积 v[i]。选取后,需要从容量 j - v[i] 的状态转移过来,并加上该物品的价值,即 dp[i-1][j - v[i]] + c[i]
初始化
dp[0][j] = 0(0 <= j <= 10):表示没有物品可选时,任何容量下的最大价值均为 0
dp[i][0] = 0(1 <= i <= n):表示容量为 0 时,无法放入任何物品,最大价值为 0
由于 C++ 全局数组默认初始化为 0,因此无需显式初始化
遍历顺序
外层循环遍历物品编号 i,从 1 到 n;
内层循环遍历容量 j,从 0 到 10(顺序遍历即可,因为二维数组中的 dp[i] 只依赖 dp[i-1] 行的数据,不会产生覆盖问题)
最终答案
输出 dp[n][10],即考虑全部 n 件物品、背包容量为 10 时的最大价值
三、代码实现
#include <iostream>
#include <algorithm> // 使用 std::max
using namespace std;
const int CAPACITY = 10; // 背包固定容量
// 定义全局数组,自动初始化为 0
// dp[i][j] 表示前 i 件物品,容量为 j 时的最大价值
int dp[105][15]; // n <= 100,故行数开 105;容量 <= 10,列数开 15
int main() {
int n;
cin >> n;
int v[105], c[105]; // 体积数组和价值数组,从下标 1 开始存储
// 输入体积
for (int i = 1; i <= n; i++) {
cin >> v[i];
}
// 输入价值
for (int i = 1; i <= n; i++) {
cin >> c[i];
}
// 动态规划主过程
for (int i = 1; i <= n; i++) { // i 表示当前考虑的物品编号
for (int j = 0; j <= CAPACITY; j++) { // j 表示当前可用容量
// 情况1:不取第 i 件物品,直接继承上一行的结果
dp[i][j] = dp[i - 1][j];
// 情况2:如果当前容量足够放下第 i 件物品,尝试选取
if (j >= v[i]) {
// 取“不取”和“取”这两种情况中的较大值
dp[i][j] = max(dp[i][j], dp[i - 1][j - v[i]] + c[i]);
}
}
}
// 输出考虑所有物品、容量为 10 时的最大价值
cout << dp[n][CAPACITY] << endl;
return 0;
}
四、总结
这道题其实就是一个 “选还是不选” 的决策问题
我们可以这样想:
行表示“已经看了前几件商品”
列表示“背包还剩多大容量”
格子里填的是“当前情况下能拿到的最大价值”
每加入一件新商品时,我们只需要比较两种情况:
不拿:价值和之前一样
拿(前提是装得下):腾出空间,加上这件商品的价值
两者取更优的那个
最后得到的数字,就是答案
这个我真的做了很久,点赞+关注,求求了
全部评论 1
真的做了很久,大家看到了都点个赞呗
2026-07-30 来自 广东
0

有帮助,赞一个