虽然之前也总结过动态规划,但是最近遇到了完全背包问题,感觉有点陌生,所以总结一下
动态规划:
之前总结过,简单的定义在之前博客都有
动态规划问题的关键就是找到状态方程
1. 01背包问题
- 01背包在牛客网和leetcode都比较常见,写法也很简单
- 题目内容:有 n 种物品,每种物品的重量是weight[ i ],价值是value[ i ] , 背包能承受的重量是 m
- 要求在每种物品只有一份的情况下,输出背包承重范围内的最大价值和,并且每样物品可以放也可以不放
代码如下:
#include <iostream>
using namespace std;
int weight[20 + 1];
int value[20 + 1];
int f[1001];
int main() {
int n, m;
cout << "请输入物品个数:";
cin >> n;
cout << "请分别输入物品的重量和价值:" << endl;
for (int i = 1; i <= n; i++) {
cin >> weight[i] >> value[i];
}
cout << "请输入背包容量:";
cin >> m;
for (int i = 1; i <= n; i++) {
for (int j = m; j >= 1; j--) {
if (weight[i] <= j) {
//状态方程,从后向前遍历
//实际f[j-weight[i]]+[i],属于一种性价比比较
//是否在这个重量范围内v[i]的价值最高
f[j]=max(f[j],f[j-weight[i]]+value[i]);
}
}
}
cout << "背包能放的最大价值为:" << f[m] << endl;
}
2. 完全背包
- 完全背包是在01背包基础上将每个物品可以有无限个刚入背包
- 例如:有n种物品,背包承受重量为m,每个物品的重量为w[ i ],价值为v[i].
- 输入:
n : 3
m : 10
3 ; 5
7 ; 6
5 ; 11
- 输出:22 (背包装5+5,价值为22)
代码如下
#include<bits/stdc++.h>
//完全背包问题
using namespace std;
int main(){
int n, m;
cout << "请输入物品总个数" << endl;
cin >> n;
cout << "背包重量" << endl;
cin >> m;
cout << "输入价值和体积" << endl;
vector<int>v(n+1), w(n+1);
vector<int>f(501);
for (int i = 1; i <= n; i++)
{
cin >> w[i] >> v[i];
}
//实现原理,在f[]中从第一个物品开始计算最大价值
//第二个物品开始在原有f[]上刷新最大值
//然后将f[i]和f[j-w[i]]进行对比
for (int i = 1; i <= n; i++){
for (int j = w[i]; j <= m; j++){
f[j] = max(f[j], f[j - w[i]] + v[i]);
}
}
cout << f[m];
system("pause");
return 0;
}