算法基础课第五讲 动态规划
时间复杂度:状态数量转移的计算量*
背包问题
- 总体概述:给一堆物品,有体积有价值。有一个背包,在背包能装下的前提下最终能装下多少(背包不一定要装满)
- DP问题:一般需要从两方面考虑:状态表示以及状态计算
- 状态表示:f(i,j) 从两个方面考虑:集合(所有选法的集合)(01背包问题需要满足两个条件:只从前i个物品中选,总体积<=j)和属性(最大值、最小值、数量)
- 状态计算:f(N,V) 表示集合的划分(不重不漏)(01背包问题不包含第i个物品、包含第i个物品)
- DP问题的优化:对表达式进行转化
01背包问题(每个物品只能用一次)
解题思路:
朴素算法:
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1010;
int n, m;
int v[N], w[N];//体积 价值
int f[N][N];
int main()
{
cin >> n >> m;
for (int i = 1;i <= n;i++)cin >> v[i] >> w[i];
for(int i=1;i<=n;i++)
for (int j = 0;j <= m;j++)
{
f[i][j] = f[i - 1][j];
if (j >= v[i])f[i][j] = max(f[i][j], f[i - 1][j - v[i]] + w[i]);
}
cout << f[n][m] << endl;
return 0;
}
改善版算法:(使用滚动数组)(循环体积的时候从大到小循环)
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1010;
int n, m;
int v[N], w[N];
int f[N];
int main()
{
cin >> n >> m;
for (int i = 1;i <= n;i++)cin >> v[i] >> w[i];
for (int i = 1;i <= n;i++)
for (int j = m;j >= v[i];j--)
f[j] = max(f[j], f[j - v[i]] + w[i]);
cout << f[m] << endl;
return 0;
}
完全背包问题(每件物品有无限个)
思路:
完全背包问题的状态转移方程:**f[i][j]=f[i-1,j-v[i]k]+w[i]k
朴素算法
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1010;
int n, m;
int v[N], w[N];
int f[N][N];
int main()
{
cin >> n >> m;
for (int i = 1;i <= n;i++)cin >> v[i] >> w[i];//读入数据
for (int i = 1;i <= n;i++)
for (int j = 0;j <= m;j++)//枚举所有状态
for (int k = 0;k * v[i] <= j;k++)//枚举物品个数
f[i][j] = max(f[i][j], f[i - 1][j - v[i] * k] + w[i] * k);
cout << f[n][m] << endl;
return 0;
}
改良版:
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1010;
int n, m;
int v[N], w[N];
int f[N][N];
int main()
{
cin >> n >> m;
for (int i = 1;i <= n;i++)cin >> v[i] >> w[i];
for(int i=1;i<=n;i++)
for (int j = 0;j <= n;j++)
{
f[i][j] = f[i - 1][j];
if (j >= v[i])f[i][j] = max(f[i][j], f[i][j - v[i]] + w[i]);
}
cout << f[n][m] << endl;
return 0;
}
改良版:
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1010;
int n, m;
int v[N], w[N];
int f[N];
int main()
{
cin >> n >> m;
for (int i = 1;i <= n;i++)cin >> v[i] >> w[i]