东方博宜OJ 1780:采灵芝 ← 完全背包问题

​【题目来源】
https://oj.czos.cn/p/1780

【题目描述】
仙岛上种了无数的不同种类的灵芝,小芳跟着爷爷来到仙岛采摘灵芝。由于他们带的食物和饮用水有限,必须在时间 t 内完成采摘。
假设岛上有 m 种不同种类的灵芝,每种灵芝都有无限多个,已知每种灵芝采摘需要的时间,以及这种灵芝的价值。
请你编程帮助小芳计算,在有限的时间 t 内,能够采摘到的灵芝的最大价值是多少?

【输入格式】
输入第一行有两个整数 T(1≤T≤100000)和 M(1≤M≤2000),用一个空格隔开,T 代表总共能够用来采灵芝的时间,M 代表岛上灵芝的种类数。
接下来的 M 行每行包括两个在 1 到 10000 之间(包括 1 和 10000)的整数,分别表示采摘某种灵芝的时间和这种灵芝的价值。

【输出格式】
输出一行,这一行只包含一个整数,表示在规定的时间内,可以采到的灵芝的最大总价值。

【输入样例】
70 3
71 100
69 1
1 2

【输出样例】
140

【数据范围】
1≤T≤100000,1≤M≤2000

【算法分析】
● 完全背包在问题结构上与 0/1 背包相似,二者均以背包容量为约束、以总价值最大化为优化目标,并均可采用动态规划方法求解;二者的本质区 别在于物品的可选取次数:在 0/1 背包中,每种物品仅有一个,仅存在选或不选两种决策;而在完全背包中,每种物品可被重复选取多次,决策 空间扩展为选取该物品的非负整数次数。

● **注意:**完全背包与 0/1 背包两者的一维状态转移方程完全相同,由遍历顺序决定是 0/1 背包还是完全背包。
(1)0/1 背包一维 DP 核心代码:逆序遍历体积。
(2)完全背包一维 DP 核心代码:正序遍历体积。

【算法代码】

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

const int maxn=1e5+5;
int vol[maxn],val[maxn];
int f[maxn];
int n,V;

int main() {
    cin>>V>>n;
    for(int i=1; i<=n; i++) {
        cin>>vol[i]>>val[i];
    }

    for(int i=1; i<=n; i++) {
        for(int j=vol[i]; j<=V; j++) {
            f[j]=max(f[j],f[j-vol[i]]+val[i]);
        }
    }
    cout<<f[V];

    return 0;
}

/*
in:
70 3
71 100
69 1
1 2

out:
140
*/

【参考文献】
https://blog.csdn.net/hnjzsyjyj/article/details/147341514
https://blog.csdn.net/hnjzsyjyj/article/details/147333181
https://blog.csdn.net/hnjzsyjyj/article/details/147326357
https://blog.csdn.net/hnjzsyjyj/article/details/125939103

相关推荐
阳洞洞1 年前
leetcode 279. Perfect Squares
算法·leetcode·动态规划·完全背包问题
阳洞洞1 年前
leetcode 322. Coin Change
算法·leetcode·动态规划·完全背包问题
阳洞洞1 年前
leetcode 377. Combination Sum IV
算法·leetcode·动态规划·完全背包问题