多重背包问题(二)

简介: AcWing算法提高课内容,本文讲解 动态规划

多重背包问题 III

题目要求

题目描述:

image.png

输入格式:

image.png

输出格式:

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

数据范围:

image.png

输入样例:

4 5
1 2 3
2 4 1
3 4 3
4 5 2

输出样例:

10

思路分析

本题用到了单调队列(滑动窗口进行优化),对该知识点不了解或不熟悉的同学请先读博客:单调队列,附上一张y总讲课截图辅助理解:

4.png

image.png

代码

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 1010, M = 20010;
int v[N], w[N], s[N];
int f[N][M];
int q[M];
int main()
{
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i ++ ) cin >> v[i] >> w[i] >> s[i];
    for (int i = 1; i <= n; i ++ ) 
    {
        for (int r = 0; r < v[i]; r ++ )
        {
            int hh = 0, tt = -1;
            for (int j = r; j <= m; j += v[i] )
            {
                while (hh <= tt && j - q[hh] > s[i] * v[i]) hh ++;
                while (hh <= tt && f[i - 1][q[tt]] + (j - q[tt]) / v[i] * w[i] <= f[i - 1][j]) tt --;
                q[ ++ tt] = j;
                f[i][j] = f[i - 1][q[hh]] + (j - q[hh]) / v[i] * w[i];
            }
        }
    }
    cout << f[n][m] << endl;
    return 0;
}

多重背包问题 I 一样的优化方式,我们发现在计算f[i][j]的时候只使用了f[i1][j]但是不可以使用 01背包的优化方法,因为我们使用的是 滑动窗口,这致使我们只能正向枚举体积。

滚动数组

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 20010;
int f[2][N];
int q[N];
int main()
{
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i ++ ) 
    {
        int v, w, s;
        cin >> v >> w >> s;
        for (int r = 0; r < v; r ++ )
        {
            int hh = 0, tt = -1;
            for (int j = r; j <= m; j += v)
            {
                while (hh <= tt && j - q[hh] > s * v) hh ++;
                while (hh <= tt && f[(i - 1) & 1][q[tt]] + (j - q[tt]) / v * w <= f[(i - 1) & 1][j]) tt --;
                q[ ++ tt] = j;
                f[i & 1][j] = f[(i - 1) & 1][q[hh]] + (j - q[hh]) / v * w;
            }
        }
    }
    cout << f[n & 1][m] << endl;
    return 0;
}

拷贝数组

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 20010;
int f[N], g[N];
int q[N];
int main()
{
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i ++ )
    {
        memcpy(g, f, sizeof f);
        int v, w, s;
        cin >> v >> w >> s;
        for (int r = 0; r < v; r ++ )
        {
            int hh = 0, tt = -1;
            for (int j = r; j <= m; j += v)
            {
                while (hh <= tt && j - q[hh] > v * s) hh ++;
                while (hh <= tt && g[q[tt]] + (j - q[tt]) / v * w <= g[j]) tt --;
                q[ ++ tt] = j;
                f[j] = g[q[hh]] + (j - q[hh]) / v * w;
            }
        }
    }
    cout << f[m] << endl;
    return 0;
}

庆功会

题目要求

题目描述:

为了庆贺班级在校运动会上取得全校第一名成绩,班主任决定开一场庆功会,为此拨款购买奖品犒劳运动员。

期望拨款金额能购买最大价值的奖品,可以补充他们的精力和体力。

输入格式:

第一行二个数 n ,m ,其中 n 代表希望购买的奖品的种数,m  表示拨款金额。


接下来 n  行,每行 3 个数,v 、w 、s ,分别表示第I种奖品的价格、价值(价格与价值是不同的概念)和能购买的最大数量(买0件到s件均可)。

输出格式:

一行:一个数,表示此次购买能获得的最大的价值(注意!不是价格)。

数据范围:

n500,m6000,

v100,w1000,s10

输入样例:

5 1000
80 20 4
40 50 9
30 50 7
40 30 6
20 20 1

输出样例:

1040

思路分析

裸题,不做解释,本题用最暴力的解法即可 A C ,有兴趣的读者可以对代码进行二进制优化和单调队列的优化,优化后的代码会放到评论区。

代码

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 6010;
int f[N];
int main()
{
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i ++ )
    {
        int v, w, s;
        cin >> v >> w >> s;
        for (int j = m; j; j -- )
            for (int k = 0; k <= s && k * v <= j; k ++ )
                f[j] = max(f[j], f[j - k * v] + k * w);
    }
    cout << f[m] << endl;
    return 0;
}




目录
相关文章
|
9月前
多重背包问题
多重背包问题
72 0
|
4月前
|
存储 算法
细谈多重背包问题
细谈多重背包问题
细谈多重背包问题
|
4月前
|
算法
浅谈完全背包问题
浅谈完全背包问题
|
9月前
多重背包和分组背包
多重背包和分组背包
|
9月前
完全背包问题
完全背包问题
64 0
|
算法 C语言 C++
【动态规划】多重背包问题,分组背包问题
与完全背包问题不同的是,每种东西都是有限件,前两种状态就不再过多赘述
158 4
动态规划——多重背包、分组背包
动态规划——多重背包、分组背包
74 0
动态规划:多重背包问题
动态规划:多重背包问题
82 0
|
算法 C++
|
算法
多重背包问题(一)
AcWing算法提高课内容,本文讲解 动态规划
149 0
多重背包问题(一)