背包问题总结

本文深入探讨了各种类型的背包问题,包括01背包、完全背包、多重背包、混合背包、二维费用背包、分组背包、有依赖的背包、背包问题求方案数及具体方案。通过详细的代码示例,为读者提供了全面的背包问题解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.01背包

01背包问题

#include <cstdio>
#include <stack>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#include <map>
#include <vector>
#include <queue>
#include <set>
#define eps 1e-8
typedef long long ll;
const double PI = acos(-1.0);
const int maxn = 1e6;
const int INF = 0x3f3f3f;
const ll linf = 0x3f3f3f3f3f3f3f3f;
using namespace std;
int f[maxn];
int v[maxn],w[maxn];
int n,V;
int main()
{
    cin>>n>>V;
    for(int i = 1; i<=n; i++)
        cin>>v[i]>>w[i];
    f[0] = 0;
    for(int i = 1; i<=n; i++)
        for(int j = V; j>=v[i]; j--)
            f[j] = max(f[j],f[j-v[i]]+w[i]);
    cout<<f[V]<<endl;

    return 0;
}

2.完全背包

完全背包问题

#include <cstdio>
#include <stack>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#include <map>
#include <vector>
#include <queue>
#include <set>
#define eps 1e-8
typedef long long ll;
const double PI = acos(-1.0);
const int maxn = 1e6;
const int INF = 0x3f3f3f;
const ll linf = 0x3f3f3f3f3f3f3f3f;
using namespace std;
int f[maxn];
int v[maxn],w[maxn];
int n,V;
int main()
{
    cin>>n>>V;
    for(int i = 1; i<=n; i++)
        cin>>v[i]>>w[i];
    f[0] = 0;
    for(int i = 1; i<=n; i++)
        for(int j = v[i]; j<=V; j++)
            f[j] = max(f[j],f[j-v[i]]+w[i]);
    cout<<f[V]<<endl;

    return 0;
}

3.多重背包

多重背包问题(二进制拆分)

二进制拆分

#include <cstdio>
#include <stack>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#include <map>
#include <vector>
#include <queue>
#include <set>
#define eps 1e-8
typedef long long ll;
const double PI = acos(-1.0);
const int maxn = 1e6;
const int INF = 0x3f3f3f;
const ll linf = 0x3f3f3f3f3f3f3f3f;
using namespace std;
int f[maxn];
int v,w,s;
int n,V;
struct node
{
    int v;
    int w;
}a[maxn];
int main()
{
    cin>>n>>V;
    f[0] = 0;
    int cnt = 0;
    for(int i = 1; i<=n; i++)
    {
        cin>>v>>w>>s;
        for(int j = 1; j<=s; j*=2)
        {
            a[++cnt].v = j*v;
            a[cnt].w = j*w;
            s -= j;
        }
        if(s)
        {
            a[++cnt].v = s*v;
            a[cnt].w = s*w;
        }
    }
    for(int i = 1; i<=cnt; i++)
        for(int j = V; j>=a[i].v; j--)
            f[j] = max(f[j],f[j-a[i].v]+a[i].w);
    cout<<f[V]<<endl;

    return 0;
}

单调队列优化(待补)

多重背包问题(单调队列优化)

4.混合背包

混合背包问题

#include <cstdio>
#include <stack>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#include <map>
#include <vector>
#include <queue>
#include <set>
#define eps 1e-8
typedef long long ll;
const double PI = acos(-1.0);
const int maxn = 1e6;
const int INF = 0x3f3f3f;
const ll linf = 0x3f3f3f3f3f3f3f3f;
using namespace std;
int f[maxn];
int v,w,s;
int n,V;
struct node
{
    int v;
    int w;
    int type;
}a[maxn];
int main()
{
    cin>>n>>V;
    f[0] = 0;
    int cnt = 0;
    for(int i = 1; i<=n; i++)
    {
        cin>>v>>w>>s;
        if(s == -1)
        {
            a[++cnt].v = v;
            a[cnt].w = w;
            a[cnt].type = 1;
        }
        else if(s>0)
        {
            for(int j = 1; j<=s; j*=2)
            {
                a[++cnt].v = j*v;
                a[cnt].w = j*w;
                a[cnt].type = 1;
                s -= j;
            }
            if(s)
            {
                a[++cnt].v = s*v;
                a[cnt].w = s*w;
                a[cnt].type = 1;
            }
        }
        else
        {
            a[++cnt].v = v;
            a[cnt].w = w;
            a[cnt].type = 0;
        }

    }
    for(int i = 1; i<=cnt; i++)
    {
        if(a[i].type)
        {
            for(int j = V; j>=a[i].v; j--)
                f[j] = max(f[j],f[j-a[i].v]+a[i].w);
        }
        else
        {
            for(int j = a[i].v; j<=V; j++)
                f[j] = max(f[j],f[j-a[i].v]+a[i].w);
        }
    }

    cout<<f[V]<<endl;

    return 0;
}

5.二维费用背包

二维费用背包问题

#include <cstdio>
#include <stack>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#include <map>
#include <vector>
#include <queue>
#include <set>
#define eps 1e-8
typedef long long ll;
const double PI = acos(-1.0);
const int maxn = 1005;
const int INF = 0x3f3f3f;
const ll linf = 0x3f3f3f3f3f3f3f3f;
using namespace std;
int f[maxn][maxn];
int v,w,m;
int n,V,M;
int main()
{
    cin>>n>>V>>M;
    f[0][0] = 0;
    int cnt = 0;
    for(int i = 1; i<=n; i++)
    {
        cin>>v>>m>>w;
        for(int j = V; j>=v; j--)
            for(int k = M; k>=m; k--)
                f[j][k] = max(f[j][k],f[j-v][k-m]+w);
    }

    cout<<f[V][M]<<endl;

    return 0;
}

6.分组背包

分组背包问题

#include <cstdio>
#include <stack>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#include <map>
#include <vector>
#include <queue>
#include <set>
#define eps 1e-8
typedef long long ll;
const double PI = acos(-1.0);
const int maxn = 1005;
const int INF = 0x3f3f3f;
const ll linf = 0x3f3f3f3f3f3f3f3f;
using namespace std;
int f[maxn];
int s;
int v[maxn],w[maxn];
int n,V,M;
int main()
{
    cin>>n>>V;
    f[0] = 0;
    for(int i = 0; i<n; i++)
    {
        cin>>s;
        for(int j = 1; j<=s; j++)
            cin>>v[j]>>w[j];
        for(int j = V; j>=0; j--)
            for(int k = 1; k<=s; k++)
        {
            if(j>=v[k])
                f[j] = max(f[j],f[j-v[k]]+w[k]);
        }
    }
    cout<<f[V]<<endl;

    return 0;
}

7.有依赖的背包

有依赖的背包问题

#include <cstdio>
#include <stack>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#include <map>
#include <vector>
#include <queue>
#include <set>
#define eps 1e-8
typedef long long ll;
const double PI = acos(-1.0);
const int maxn = 1005;
const int INF = 0x3f3f3f;
const ll linf = 0x3f3f3f3f3f3f3f3f;
using namespace std;
int nxt[maxn],head[maxn],ver[maxn];
int f[maxn][maxn];
int n,V;
int v[maxn],w[maxn];
int tot;
void add(int x, int y)
{
    ver[++tot] = y;
    nxt[tot] = head[x];
    head[x] = tot;
}
void dfs(int u)
{
    for(int i = head[u]; i; i = nxt[i])
    {
        int son = ver[i];
        dfs(son);
        for(int j = V-v[u]; j>=0; j--)
            for(int k = 0; k<=j; k++)
                f[u][j] = max(f[u][j],f[u][j-k]+f[son][k]);
    }
    for(int i = V; i>=v[u]; i--)
        f[u][i] = f[u][i-v[u]]+w[u];
    for(int i = 0; i<v[u]; i++)
        f[u][i] = 0;
}
int main()
{
    tot = 0;
    cin>>n>>V;
    int root;
    for(int i = 1; i<=n; i++)
    {
        int fa;
        cin>>v[i]>>w[i]>>fa;
        if(fa != -1)
            add(fa,i);
        else
            root = i;
    }
    dfs(root);
    cout<<f[root][V]<<endl;

    return 0;
}

8.背包问题求方案数

背包问题求方案数

#include <cstdio>
#include <stack>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#include <map>
#include <vector>
#include <queue>
#include <set>
#define eps 1e-8
typedef long long ll;
const double PI = acos(-1.0);
const int maxn = 1005;
const int INF = 0x3f3f3f;
const ll linf = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
using namespace std;
int f[maxn],g[maxn];
int n,V;
int main()
{

    cin>>n>>V;
    memset(f,0xcf,sizeof f);
    f[0] = 0;
    g[0] = 1;
    for(int i = 0; i<n; i++)
    {
        int v,w;
        cin>>v>>w;
        for(int j = V; j>=v; j--)
        {
            int tmp = max(f[j],f[j-v]+w);
            int s = 0;
            if(tmp == f[j])
                s = g[j]%mod;
            if(tmp == f[j-v]+w)
                s = (s+(g[j-v]%mod))%mod;
            f[j] = tmp;
            g[j] = s;
        }
    }
    int maxw = 0;
    for(int i = 0; i<=V; i++)
        maxw = max(maxw,f[i]);
    int res = 0;
    for(int i = 0; i<=V; i++)
    {
        if(f[i] == maxw)
        {
            res = ((res%mod)+(g[i]%mod))%mod;
        }
    }
    cout<<res<<endl;

    return 0;
}

9.背包问题求具体方案

背包问题求具体方案

#include <cstdio>
#include <stack>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#include <map>
#include <vector>
#include <queue>
#include <set>
#define eps 1e-8
typedef long long ll;
const double PI = acos(-1.0);
const int maxn = 1005;
const int INF = 0x3f3f3f;
const ll linf = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
using namespace std;
int f[maxn][maxn];
int v[maxn],w[maxn];
int n,V;
int main()
{

    cin>>n>>V;
    for(int i = 1; i<=n; i++)
        cin>>v[i]>>w[i];
    for(int i = n; i>0; i--)
    {
        for(int j = 0; j<=V; 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]);
        }
    }
    int vol = V;
    for(int i = 1; i<=n; i++)
    {
        if(vol>=v[i] && f[i][vol] == f[i+1][vol-v[i]]+w[i])
        {
            cout<<i<<" ";
            vol -= v[i];
        }
    }

    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值