背包问题
AcWing 2. 01背包问题
- 二维解法
f[i][j]表示编号不超过i的体积不超过j的最大价值
每次选择都是分成第i个选与第i个不选
不选第i个时 f[i][j]=f[i][j-1] 选择第i个时 体积减少v[i] 价值增加w[i];
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int n, m;
int v[N], w[N];
int f[N][N]; //f[i][j]表示编号不超过i的体积不超过j的最大价值
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> v[i] >> w[i];
}
//f[0][0 - m] = 0 // 选择0件物品 价值都是0;
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-1][j],f[i-1][j-v[i]]+w[i]);
}
}
cout<<f[n][m];
}
- 一维解法
由二维解法推到一维解法
若直接删除第一维 f[i][j] = f[i - 1][j];变为 f[j] = f[j]与之前等价 此行删除
if(j>=v[i]) 则j从0-v[i]便无意义 for循环改为for (int j = v[i]; j<=m; j++)
若这样改 这样改相当于f[i][j]=max(f[i-1][j],f[i][j-v[i]]+w[i]);则与原式不等价
j-v[i]严格小于j 但是 j是从小到大枚举的 算f[j]的时候 f[j-v[i]]在第i层已经被计算过了
因此j从大到小循环就可以
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int n, m;
int v[N], w[N];
int f[N]; //f[i][j]表示编号不超过i的体积不超过j的最大价值
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> v[i] >> w[i];
}
// f[0][0 - m] = 0 // 选择0件物品 价值都是0;
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[n][m];
}
**AcWing 3. 完全背包问题
二维解法
时间复杂度O(n^3)复杂度太高(超时)
#include <bits/stdc++.h>
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] + k * w[i]);
}
}
}
cout << f[n][m];
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 = v[i]; j <= m; j ++ )
f[j] = max(f[j], f[j - v[i]] + w[i]);
cout << f[m] << endl;
return 0;
}
AcWing 4. 多重背包问题
AcWing 5. 多重背包问题 II
AcWing 9. 分组背包问题**
线性DP
AcWing 898. 数字三角形
AcWing 895. 最长上升子序列
AcWing 896. 最长上升子序列 II
AcWing 897. 最长公共子序列
AcWing 902. 最短编辑距离
AcWing 899. 编辑距离
区间DP
AcWing 282. 石子合并
计数类DP
AcWing 900. 整数划分
数位统计DP
AcWing 338. 计数问题
状态压缩DP
AcWing 291. 蒙德里安的梦想
AcWing 91. 最短Hamilton路径
树形DP
AcWing 285. 没有上司的舞会
记忆化搜索
AcWing 901. 滑雪