背包九讲专题

这篇博客详细讲解了背包问题的多个变种,包括01背包、完全背包、多重背包及其各种优化问题,如二维费用的背包、分组背包、有依赖的背包等,旨在帮助读者全面理解并解决这类经典动态规划问题。
摘要由CSDN通过智能技术生成

1 01背包问题
2 完全背包问题
3 多重背包问题
4 混合背包问题
5 二维费用的背包问题
6 分组背包问题
7 有依赖的背包问题
8 背包问题求方案数
9 背包问题求具体方案

01背包问题

有 N 件物品和一个容量是 V的背包。每件物品只能使用一次。

第 i件物品的体积是 vi,价值是 wi。

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。

输入格式
第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。

接下来有 N行,每行两个整数 vi,wi,用空格隔开,分别表示第 i件物品的体积和价值。

输出格式
输出一个整数,表示最大价值。

数据范围
0<N,V≤1000
0<vi,wi≤1000

输入样例
4 5
1 2
2 4
3 4
4 5

输出样例:
8

/*

f[i][j] 表示只看前i个物品,总体积是j的情况下,总价值最大是多少

result = max(f[n][0 ~ v])

f[i][j]:

1.不选第i个物品, f[i][j] = f[i - 1][j];
2.选第i 个物品,  f[i][j] = f[i - 1][j - v[i]];

f[i][j] = max(1, 2)

f[0][0] = 0;

*/

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1010;

int n, m;
int f[N][N];
int v[N], w[N]; //体积 价值

int main()
{
   
    cin >> n >> m;
    for(int i = 1; i <= n; i++) cin >> v[i] >> w[i];
    
    for(int i = 1; i <= n; i++)
        for(int j = 0; j <= m; 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 res = 0;
    for(int i = 0; i <= m; i++) res = max(res, f[n][i]);
    
    cout << res << endl;
    return 0;
}

优化

/*

f[i][j] 表示只看前i个物品,总体积是j的情况下,总价值最大是多少

result = max(f[n][0 ~ v])

f[i][j]:

1.不选第i个物品, f[i][j] = f[i - 1][j];
2.选第i 个物品,  f[i][j] = f[i - 1][j - v[i]];

f[i][j] = max(1, 2)

f[0][0] = 0;

*/

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1010;

int n, m;
int f[N]; //优化1 把二维数组变成一维数组 体积是i的时候最大价值是多少
int v[N], w[N]; //体积 价值

int main()
{
   
    cin >> n >> m;
    for(int i = 1; i <= n; i++) cin >> v[i] >> w[i];
    
    for(int i = 1; i <= n; i++)
        for(int j = m; j >= v[i]; j--) //从大到小枚举 保证下面算的时候 是 i-1 不是 i
                f[j] = max(f[j], f[j - v[i]] + w[i]);//选
   
    cout << f[m] << endl; //优化2 f[m]
    return 0;
}

完全背包问题

有 N 种物品和一个容量是 V的背包,每种物品都有无限件可用。

第 i种物品的体积是 vi,价值是 wi。

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。

输入格式

第一行两个整数,N,V,用空格隔开,分别表示物品种数和背包容积。

接下来有 N行,每行两个整数 vi,wi,用空格隔开,分别表示第 i种物品的体积和价值。

输出格式
输出一个整数,表示最大价值。

数据范围
0<N,V≤1000
0<vi,wi≤1000

输入样例
4 5
1 2
2 4
3 4
4 5

输出样例:
10

/*

f[i] 表示 总体积是i的情况下,最大价值是多少

result = max(f[0 ... m)

for(int i = 0; i < n; i++)
{
    for(int j = v[i]; j <= m; j++)
        f[j] = max(f[j], f[j - v[i] + w[i]);
        
    for(int j = m; j >= v[i]; j --)
        for(int k = 0; k * v[i] <= j; k++)
            f[j] = max(f[j], f[j - k * v[i]] + k * w[i]);
}

*/

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1010;

int n, m;
int f[N];

int main()
{
   
    cin >> n >> m;
    for(int i = 0; i < n; i ++)
    {
   
        int v, w;
        cin >> v >> w;
        for(int j = v; j <= m; j++)
            f[j] = max(f[j], f[j - v] + w);
    }
    
    cout << f[m] <<endl;
    return 0;
}

小结 !!!

01背包:每件物品只能用一次 第一重循环循环物品 第二重循环体积从大到小枚举
完全背包:每件物品能用无限次 第一重循环不变 第二重循环从小到大枚举

多重背包问题 I

有 N 种物品和一个容量是 V的背包。

第 i种物品最多有 si 件,每件体积是 vi,价值是 wi。

求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。

输入格式
第一行两个整数,N,V,用空格隔开,分别表示物品种数和背包容积。

接下来有 N行,每行三个整数 vi,wi,si,用空格隔开,分别表示第 i种物品的体积、价值和数量。

输出格式
输出一个整数,表示最大价值。

数据范围
0<N,V≤100
0<vi,wi,si≤100

输入样例
4 5
1 2 3
2 4 1
3 4 3
4 5 2

输出样例:
10

/*

f[i] 总体积是i的情况下,最大价值是多少

for(int i = 0; i < n; i++)
{
    for(int j = m; j >= v[i]; j --)
        f[j] = max(f[j], f[j - v[i] + w[i]); 01背包
        f[j] = max(f[j], f[j - v[i] + w[i], f[j - 2 * v[i] + 2 * w[i] ...); 选多个 01背包的拓展 也要从大到小枚举
}

1. f[i] = 0 都已经初始化
f[m]

2.f[0] = 0  f[i] = -INF, i != 0;
max(f[0 ... m]) 枚举所有 求最大值

*/

#include <iostream>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值