背包九讲学习

1、0-1背包问题
在这里插入图片描述
空间优化方案

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int N, V;
    cin >> N >> V;
    
    vector<int> v(N);
    vector<int> w(N);
    
    for(int i = 0; i < N; i++)
    {
        cin >> v[i] >> w[i];
    }
    
    vector<int> dp(V + 1);
    for(int i = 0; i < N; i++)
    {
        for(int j = V; j >= v[i]; j--)
        {
            dp[j] = max(dp[j], dp[j - v[i]] + w[i]);
        }
    }
    cout << dp[V] <<endl;
    return 0;
}

2、完全背包问题
每个物体可以无限次使用
对于体积,从前往后走 保证物体可以取多次

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int N, V;
    cin >> N >> V;
    
    vector<int> v(N);
    vector<int> w(N);
    
    for(int i = 0; i < N; i++)
    {
        cin >> v[i] >> w[i];
    }
    
    vector<int> dp(V + 1);
    for(int i = 0; i < N; i++)
    {
        for(int j = v[i]; j <= V; j++)
        {
            dp[j] = max(dp[j], dp[j - v[i]] + w[i]);
        }
    }
    cout << dp[V] <<endl;
    return 0;
}

3、多重背包问题
在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int N, V;
    cin >> N >> V;
    
    vector<int> v(N);
    vector<int> w(N);
    vector<int> s(N);
    
    for(int i = 0; i < N; i++)
    {
        cin >> v[i] >> w[i] >> s[i];
    }
    
    vector<int> dp(V + 1);
    for(int i = 0; i < N; i++)
    {
        for(int j = V; j >= v[i]; j--)
        {
            for(int k = 1; k <= s[i] && k * v[i] <= j; k++)
            {
                dp[j] = max(dp[j], dp[j - k * v[i]] + k * w[i]);
            }
        }
    }
    cout << dp[V] << endl;
    return 0;
}

4、多重背包问题优化
1、二进制优化

#include <bits/stdc++.h>
using namespace std;

struct Good
{
    int v;
    int w;
};

int main()
{
    int N, V;
    cin >> N >> V;
    
    vector<Good> res;
    int v, w, s;
    
    for(int i = 0; i < N; i++)
    {
        cin >> v >> w >> s;
        for(int k = 1; k <= s; k *= 2) //将s个物品拆分,转换为0-1背包问题
        {
            s -= k;
            res.push_back({k * v, k * w});
        }
        if(s > 0)
            res.push_back({s * v, s * w});
    }
    
    vector<int> dp(V + 1);
    for(auto good : res)
    {
        for(int j = V; j >= good.v; j--)
        {
            dp[j] = max(dp[j], dp[j - good.v] + good.w);
        }
    }
    
    cout << dp[V] << endl;
    return 0;
}

2、单调队列优化

5、混合背包问题
在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;

struct Good
{
    int kind;
    int v, w;
};

vector<Good> good;

int main()
{
    int N, V;
    
    cin >> N >> V;
    
    
    for(int i = 0; i < N; i++)
    {
        int v, w, s;
        cin >> v >> w >> s;
        
        if(s < 0)
            good.push_back({-1, v, w}); //0-1背包问题
        else if(s == 0)
            good.push_back({0, v, w});  //完全背包问题 从小到大遍历
        else
            //将多重背包问题化解为0-1背包问题
        {
            for(int k = 1; k <= s; k *= 2)
            {
                s -= k;
                good.push_back({-1, k * v, k * w});
            }
            if(s > 0)
                good.push_back({-1, s * v, s * w});
        }
    }
    
    vector<int> dp(V + 1);
    
    for(auto goo : good)
    {
        if(goo.kind == -1)
        {
            for(int j = V; j >= goo.v; j--)
            {
                dp[j] = max(dp[j], dp[j - goo.v] + goo.w);
            }
        }
        else
        {
            for(int j = goo.v; j <= V; j++)
            {
                dp[j] = max(dp[j], dp[j - goo.v] + goo.w);
            }
        }
    }
    cout << dp[V] <<endl;
    return 0;
}

6、二维费用背包问题
在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int N, V, M;
    
    cin >> N >> V >> M;
    
    vector<vector<int>> dp(V + 1, vector<int>(M + 1));
    for(int i = 0; i < N; i++)
    {
        int v, m, w;
        cin >> v >> m >> w;
        for(int j = V; j >= v; j--)
        {
            for(int k = M; k >= m; k--)
            {
                dp[j][k] = max(dp[j][k], dp[j - v][k - m] + w);
            }
        }
    }
    
   
    cout << dp[V][M] <<endl;
    return 0;
}

7、分组背包问题
在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int N, V;
    
    cin >> N >> V;
    
    vector<int> v(N);
    vector<int> w(N);
    vector<int> dp(V + 1);
    for(int i = 0; i < N; i++)
    {
        int s;
        cin >> s;
        for(int j = 0; j < s; j++)
        {
            cin >> v[j] >> w[j];
        }
        for(int j = V; j >= 0; j--)
        {
            for(int k = 0; k < s; k++)//对于每组的物品,不选或者从1选到s
            {
                if(j >= v[k])
                {
                    dp[j] = max(dp[j], dp[j - v[k]] + w[k]);
                }
                               
            }
        }
    }
    cout << dp[V] << endl;
    return 0;
}

8、背包问题方案数

#include <bits/stdc++.h>
using namespace std;

const int mod = 1e9 + 7;

int main()
{
    int N, V;
    cin >> N >> V;
    
    vector<int> dp(V + 1);
    vector<int> cnt(V + 1); //记录最优方案数
    for(int i = 0; i < V; i++)
        cnt[i] = 1; //初始化为1,即不选也是种方案
    
    for(int i = 0; i < N; i++)
    {
        int v, w;
        cin >> v >> w;
        for(int j = V; j >= v; j--)
        {
            int value = dp[j - v] + w;
            if(value > dp[j])
            {
                dp[j] = value;
                cnt[j] = cnt[j - v];
            }                
            else if(value == dp[j])
                cnt[j] = (cnt[j] + cnt[j - v]) % mod; //两种方案相加
        }
    }
    cout << cnt[V] <<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值