背包

背包问题

01背包:每个物品:选、不选

完全背包:每个物品:选0,选1个,选2个,....选无穷多个


多重背包问题(每个物品:选0....选si个)

多重背包问题Ⅰ(朴素版):

点击查看代码
// 数据范围
// 0<N,V≤100
// 0<vi,wi,si≤100
#include<iostream>
using namespace std;
const int N = 110;
int v[N], w[N], s[N];
int m, n;
int f[N][N];
int main() {
// 物品种数 背包容积
cin >> m >> n;
for (int i = 1; i <= m; i++) {
cin >> v[i] >> w[i] >> s[i];
}
for (int i = 1; i <= m; i++) {
for (int j = 0; j <= n; j++) {
for (int k = 0; k <= s[i] && k * v[i] <= j; k++) {
f[i][j] = max(f[i][j], f[i-1][j-k*v[i]] + w[i]*k);
}
}
}
cout << f[m][n] << endl;
return 0;
}

多重背包问题Ⅱ(对多重背包问题Ⅰ进行二进制的优化):

点击查看代码
// 数据范围
// 0<N≤1000
// 0<V≤2000
// 0<vi,wi,si≤2000
#include<iostream>
#include<algorithm>
using namespace std;
// 时间复杂度为N * V * logS= 1000 * 2000 * log2000
const int N = 25000;
int m, n;
int v[N], w[N], s[N];
int f[N];
int main() {
// 物品种数 背包容积
cin >> m >> n;
// 当前物品的排序
int cnt = 0;
for (int i = 1; i <= n; i++) {
int a, b, c;
// 表示体积 价值 数量
cin >> a >> b >> c;
// k表示当前选择当前物品的个数
int k = 1;
// 当选择物品个数大于给定个数时,退出循环
while (k <= c) {
cnt++;
v[cnt] = a * k;
w[cnt] = b * k;
c -= k;
k *= 2;
}
// 当还有剩余值时,继续加进来
if (c > 0) {
cnt++;
v[cnt] = a * c;
w[cnt] = b * c;
}
}
// 更新物品的个数
m = cnt;
// 将多重背包问题变成了01背包
// 对于每个组中的物品选或是不选
for (int i = 1; i <= m; i++) {
for (int j = n; j >= v[i]; j--) {
f[j] = max(f[j], f[j-v[i]] + w[i]);
}
}
cout << f[n];
return 0;
}

多重背包问题Ⅲ(对多重背包问题Ⅰ进行单调队列优化/滑动窗口求数值):(不太懂)



点击查看代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 20010;
int n, m;
int f[N], g[N], q[N];
int main() {
// 分别表示物品种数 背包体积
cin >> n >> m;
for (int i = 0; i < n; i++) {
int v, w, s;
cin >> v >> w >> s;
// 将i-1层(上一层)的价值存储下来
memcpy(g, f, sizeof f);
for (int j = 0; j < v; j++) {
int hh = 0, tt = -1;
for (int k = j; k <= m; k += v) {
// 当整个队列中的元素超出s个时,就让队头元素出去
if (hh <= tt && q[hh] < k - s * v) {
hh++;
}
// 下标减去初始的值
// 将尾部元素的价值比当前的元素的价值小的时候,将队尾弹出
// 当前下标和该最大值的下标之间差了x个v,那么就要加上x个w
while (hh <= tt && g[q[tt]] - (q[tt] - j) / v * w <= g[k] - (k - j) / v * w) {
tt--;
}
// 如果队列不空的话,求得的是窗口内部的最大值。中间空余了x个物品,将x乘以w
if (hh <= tt) {
f[k] = max(f[k], g[q[hh]] + (k - q[hh]) / v * w);
}
q[++tt] = k;
}
}
}
cout << f[m] << endl;
return 0;
}
posted @   jsqup  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示