背包DP
Posted nioh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了背包DP相关的知识,希望对你有一定的参考价值。
0-1背包
有n种物品,每种只有一个。第i种物品的体积为Vi,重量为Wi。选一些 物品装到一个容量为C的背包,使得背包内物品在总体积不超过C的前提下重量尽量大。
$f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+w[i])$
for(int i = 1; i <= n; i++) { for(int j = 0; j <= c; j++) { f[i][j] = f[i - 1][j]; if(j >= v[i]) f[i][j] = max(f[i][j], f[i - 1][j - v[i]] + w[i]); } }
可以用滚动数组进行优化。
for(int i = 1; i <= n; i++) for(int j = c; j >= v[i]; j--) f[j] = max(f[j], f[j - v[i]] + w[i]);
例题:洛谷P1060
https://www.luogu.com.cn/problem/P1060
#include<bits/stdc++.h> using namespace std; int n, c, v, p, f[30010]; int main() { cin >> n >> c; for(int i = 0; i < n; i++) { cin >> v >> p; for(int j = c; j >= v; j--) f[j] = max(f[j], f[j - v] + v * p); } cout << f[c]; }
完全背包
有n种物品,每种均有无穷多个。第i种物品的体积为Vi,重量 为Wi。选一些物品装到一个容量为C的背包中,使得背包内物品在总体积不超过C的前提下重量尽量大。
$f[i]=max(f[i-v[j]]+w[j])$
for(int i = 1; i <= n; i++) for(int j = v[i]; j <= c; j++) f[j] = max(f[j], f[j - v[i]] + w[i]);
例题:洛谷P1616
https://www.luogu.com.cn/problem/P1616
#include<bits/stdc++.h> using namespace std; int n, c, v, w, f[100010]; int main() { cin >> c >> n; for(int i = 0; i < n; i++) { cin >> v >> w; for(int j = v; j <= c; j++) f[j] = max(f[j], f[j - v] + w); } cout << f[c]; }
多重背包
有n种物品,每种均有无穷多个。第i种物品的体积为Si,重量 为Wi。选一些物品装到一个容量为C的背包中,使得背包内物品在总体积不超过C的前提下重量尽量大。
直接摊平就转化为0-1背包,但时间复杂度会很差。可以使用二分法优化。
例题:洛谷P1776
https://www.luogu.com.cn/problem/P1776
#include<bits/stdc++.h> using namespace std; long long n, c, v[100010], w[100010], f[100010], x, y, z, p = 0; int main() { cin >> n >> c; for(int i = 0; i < n; i++) { cin >> x >> y >> z; for(int j = 1; j <= z; j <<= 1) { v[++p] = y * j; w[p] = x * j; z -= j; } if(z) v[++p] = y * z, w[p] = x * z; } for(int i = 1; i <= p; i++) for(int j = c; j >= v[i]; j--) f[j] = max(f[j], f[j - v[i]] + w[i]); cout << f[c]; }
以上是关于背包DP的主要内容,如果未能解决你的问题,请参考以下文章