什么是动态规划
动态规划通过额外的空间将已经搜索过的相似的结果(指某些具有相同性质解的集合)用一个数组存起来,所以DP
中的状态转移
看上去是某两三个值之间的推导,其实是某两三个集合之间的状态转移!
常见的背包模型
- 01背包问题
- 完全背包问题
- 多重背包问题
- 分组背包问题
传送们:动态规划- 背包问题总结(一)
多重背包模型
典型题例:
有 N 种物品和一个容量是 V 的背包。
第 i 种物品最多有 si 件,每件体积是 vi,价值是 wi。
求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。
示例 :
输入:第一行两个整数,N,V,用空格隔开,分别表示物品种数和背包容积。 接下来有 N 行,每行三个整数 vi,wi,si,用空格隔开,分别表示第 i 种物品的体积、价值和数量。 4 5 1 2 3 2 4 1 3 4 3 4 5 2
思路
与01背包 完全背包最后集合的划分,也就是状态计算不太一样。 最后的状态划分为第i个选0~k个的情况
代码:
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 110; int n, m; int f[N]; int main() { cin >> n >> m; for (int i = 0; i < n; i ++) { int v, w, s; cin >> v >> w >> s; for (int j = m; j >= 0; j --) for (int k = 1; k <= s && k * v < = j; k ++) //优化:选的个数*体积<总体积 f[j] = max(f[j], f[j - k * v] + k * w); } cout << f[m] << endl; return 0; }
分组背包问题
典型题例:
有 N 组物品和一个容量是 V 的背包。
每组物品有若干个,同一组内的物品最多只能选一个。
每件物品的体积是 vij,价值是 wij,其中 i 是组号,j 是组内编号。
求解将哪些物品装入背包,可使物品总体积不超过背包容量,且总价值最大。
输出最大价值。
示例 :
输入:第一行有两个整数 N,V,用空格隔开,分别表示物品组数和背包容量。 接下来有 N 组数据: 1)每组数据第一行有一个整数 Si,表示第 i 个物品组的物品数量; 2)每组数据接下来有 Si 行,每行有两个整数 vij,wij,用空格隔开,分别表示第 i 个物品组的第 j 个物品的体积和价值; 3 5 2 1 2 2 4 1 3 4 1 4 5 输出: 8
思路
与多重背包问题相似,多重背包问题时分组背包问题的个例
代码:
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 110; int n, m; int f[N]; // int v[N], w[N], s[N]; //s[i]第i组物品的个数 int main() { cin >> n >> m; for (int i = 0; i < n; i ++) { //枚举组别 int s = 0; cin >> s; //循环输入每组中的物品的体积和价值 for (int j = 0; j < s; j ++) cin >> v[i] >> w[i]; for (int j = m; j >= 0; j --) // for (int k = 0; k < s; k ++) //枚举每组中的一个物品 if (j >= v[k]) f[j] = max(f[j], f[j - v[k]] + w[k]); } cout << f[m] << endl; return 0; }
充电站
推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,立即学习