蓝桥杯c语言学习——背包问题
背包模型
(1)01背包
有一个体积为 V 的背包,商店有 n 个物品,每个物品有一个价值 v 和体积 w,每个物品只能被拿一次,问能够装下物品的最大价值。这里每一种物品只有两种状态即 “拿” 或 “不拿”。
设状态 dp [i][j] 表示到第 i 个物品为止,拿的物品总体积为 j 的情况下的最大价值。我们并不关心某个物品有没有被拿,只关心当前体积下的最大价值。
转移方程为:dp [i][j] = max (dp [i-1][j], dp [i-1][j-w]+v);如果不拿物品 i,那么最大价值就是 dp [i-1][j],如果拿了就是从体积 j-v 转移过来,体积会变大 w,价值增加 v。
最后输出 dp [n][V];
例子:
小明有一个容量为 V 的背包。这天他去商场购物,商场一共有 N 件物品,第 i 件物品的体积为 wᵢ,价值为 vᵢ。小明想知道在购买的物品总体积不超过 V 的情况下所能获得的最大价值为多少,请你帮他算算。
输入描述
输入第 1 行包含两个正整数 N, V,表示商场物品的数量和小明的背包容量。第 2~N + 1 行包含 2 个正整数 w, v,表示物品的体积和价值。1 ≤ N ≤ 10⁵,1 ≤ V ≤ 10³,1 ≤ wᵢ, vᵢ ≤ 10³。
输出描述
输出一行整数表示小明所能获得的最大价值。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 105, M = 1010;
ll dp[M];
int main()
{
int n, V;cin >> n >> V;
for(int i = 1;i <= n; ++i)
{
ll w, v;cin >> w >> v;
for(int j = V;j >= w; --j)
{
dp[j] = max(dp[j], dp[j - w] + v);
}
}
cout << dp[V] << '\n';
return 0;
}
(2)完全背包
完全背包也叫无穷背包,即每种物品有无数个的背包。有一个体积为 V 的背包,商店有 n 个物品,每个物品有一个价值 v 和体积 w,每个物品有无限多个,可以被拿无穷次,问能够装下物品的最大价值。这里每一种物品只有无穷种状态即 “拿 0 个、1 个、2 个… 无穷多个”。设状态 dp [j] 表示拿的物品总体积为 j 的情况下的最大价值。我们并不关心某个物品拿了几个,只关心当前体积下的最大价值。转移方程为:dp [j]=max (dp [j],dp [j-w]+v),现在就必须使用 “新数据” 来更新 “新数据”,因为新数据中包括了拿当前这个物品的状态,而当前这个物品是可以被拿无数次的。最后输出 dp [V] 即可。

浙公网安备 33010602011771号