多重背包问题与优化(裸题)(一)

简介: 多重背包问题与优化(裸题)

多重背包问题 I

题目要求

题目描述:

image.png

输入格式:

image.png

输出格式:

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

数据范围:

image.png

输入样例:

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

输出样例:

10

思路分析

数据范围很小,暴力枚举即可,不需要过多操作,f[i][j] 代表的是只从前 i 件物品中选,且总体积不超过 j的价值最大值。

代码

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

代码优化

image.png

滚动数组

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 110;
int f[2][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 = 0; j <= m; j ++ )
            for (int k = 0; k <= s && k * v <= j; k ++ )
                f[i & 1][j] = max(f[i & 1][j], f[(i - 1) & 1][j - k * v] + k * w);
    }
    cout << f[n & 1][m] << endl;
    return 0;
}

拷贝数组

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

逆循环优化

逆循环的优化方式和 01 背包的优化是相同的,原理也是一致的,对于体积逆序枚举即可实现,这样的优化方法可真正实现仅用一维数组表示二维变量:

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 110;
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;
}



目录
相关文章
|
算法 Android开发 索引
LeetCode 周赛上分之旅 #44 同余前缀和问题与经典倍增 LCA 算法
学习数据结构与算法的关键在于掌握问题背后的算法思维框架,你的思考越抽象,它能覆盖的问题域就越广,理解难度也更复杂。在这个专栏里,小彭与你分享每场 LeetCode 周赛的解题报告,一起体会上分之旅。
81 0
|
存储 人工智能 算法
【算法分析与设计】动态规划(下)(一)
【算法分析与设计】动态规划(下)
|
6月前
|
测试技术
【一刷《剑指Offer》】面试题 9:斐波那契数列(扩展:青蛙跳台阶、矩阵覆盖)
【一刷《剑指Offer》】面试题 9:斐波那契数列(扩展:青蛙跳台阶、矩阵覆盖)
|
消息中间件 人工智能 算法
【算法分析与设计】动态规划(下)(二)
【算法分析与设计】动态规划(下)
|
存储 算法
【算法分析与设计】动态规划(下)(三)
【算法分析与设计】动态规划(下)
|
C++
蓝桥杯 2240. 买钢笔和铅笔的方案数c++解法
蓝桥杯 2240. 买钢笔和铅笔的方案数c++解法
136 0
|
算法 C++
【每日算法Day 109】五大解法,带你深入了解完全背包方案数
【每日算法Day 109】五大解法,带你深入了解完全背包方案数
105 0
|
机器学习/深度学习
数论整理之特殊数two:卡特兰数
数论整理之特殊数two:卡特兰数
|
算法 C++
|
存储 算法 C语言
动态规划算法解决背包问题,算法分析与C语言代码实现,时间效率解析
动态规划算法解决背包问题,算法分析与C语言代码实现,时间效率解析
196 0