背包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的主要内容,如果未能解决你的问题,请参考以下文章

被遗忘的DP -01背包代码

$01背包详解$

hdu1561 树形dp+背包

背包问题

0/1背包

DP-背包问题