【题目来源】
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