1. 基础动态规划
1.1 最长不下降序列
题目描述:输入n个数(1 <= n <= 104),输出最长不下降序列的长度。
(1) 输出长度
#include<bits/stdc++.h>
using namespace std;
const int N = 1007, INF = 1e9 + 7;
int f[N];
int main () {
int n;
scanf("%d", &n);
fill(f, f+n, INF);
for(int i = 1, x;i <= n;++i) {
scanf("%d", &x);
int k = lower_bound(f, f+n, x) - f;
f[k] = x;
}
int k = lower_bound(f, f+n, INF) - f;
printf("%d\n", k);
return 0;
}
(2)长度+序列
需要用到递归。
#include<bits/stdc++.h>
using namespace std;
const int N = 1007, INF = 1e9 + 7;
int f[N], pr[N], a[N], b[N];
void print(int k) {
if(!k) return;
print(pr[k]);
printf("%d ", a[k]);
}
int main () {
int n;
scanf("%d", &n);
fill(f, f+n, INF);
for(int i = 1;i <= n;++i) {
scanf("%d", a+i);
int k = lower_bound(f, f+n, a[i]) - f;
f[k] = a[i], b[k] = i;
if(k) pr[i] = b[k-1];
}
int k = lower_bound(f, f+n, INF) - f;
printf("%d\n", k);
print(b[k-1]);
return 0;
}
2.背包问题
2.1 01背包
例:采药
1.二维dp
状态转移方程:f[i][j] = max(f[i-1][j], f[i-1][j-w[i]+c[i])
初始值:f[0][0] = 0
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 1;
int dp[N][N], v[N], w[N], t, m;
int main() {
scanf("%d%d",&t,&m);
for(int i = 1;i <= m;++i)
scanf("%d%d",&w[i],&v[i]);
for(int i = 1;i <= m;i++)
for(int j = 1;j <= t;j++){
dp[i][j] = dp[i-1][j];
if(j >= w[i]) dp[i][j] = max(dp[i-1][j], v[i]+dp[i-1][j-w[i]]);
}
printf("%d", dp[m][t]);
return 0;
}
内存:584KB。
2.滚动数组
如果你仔细观察,就会发现更新第i行只需要看第i-1行就可以了,所以可以用滚动数组压至两行。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 1;
int f[2][N], v, w, u = 1, t, m;
int main() {
scanf("%d%d",&t,&m);
for(int i = 1;i <= m;++i) {
scanf("%d%d", &v, &w);
for(int j = 1;j <= t;++j) {
f[u][j] = f[u^1][j];
if(j >= v) f[u][j] = max(f[u][j], f[u^1][j-v]+w);
}
u ^= 1;
}
printf("%d", f[m&1][t]);
return 0;
}
内存从584KB降到了200KB。
3.降维(最好的方法)
2.2 最长公共子序列
#include <bits/stdc++.h>
using namespace std;
char s1[250], s2[250];
int f[250][250];
int main() {
scanf("%s%s", s1 + 1, s2 + 1);
int s1s = strlen(s1 + 1), s2s = strlen(s2 + 1);
for (int i = 1; i <= s2s; ++i)
for (int j = 1; j <= s1s; ++j) {
if (s2[i] == s1[j])
f[i][j] = f[i - 1][j - 1] + 1;
else
f[i][j] = max(f[i][j - 1], f[i - 1][j]);
}
printf("%d", f[s2s][s1s]);
return 0;
}