1 基础知识
暂无。。。
2 模板
暂无。。。
3 工程化
题目1:大盗阿福。
解题思路:状态表示多了一维,取0或者取1,表示不选择第i个物品和选择第i个物品。
C++代码如下,
#include <iostream>
#include <cstring>
using namespace std;
const int N = 100010;
int n;
int w[N];
int f[N][2];
int main() {
int T;
cin >> T;
for (int C = 0; C < T; ++C) {
cin >> n;
for (int i = 1; i <= n; ++i) cin >> w[i];
//状态计算
for (int i = 1; i <= n; ++i) {
f[i][0] = f[i][1] = 0;
}
for (int i = 1; i <= n; ++i) {
f[i][0] = max(f[i-1][0], f[i-1][1]);
f[i][1] = f[i-1][0] + w[i];
}
int res = 0;
for (int i = 1; i <= n; ++i) {
res = max(res, f[i][0]);
res = max(res, f[i][1]);
}
cout << res << endl;
}
return 0;
}
题目2:股票买卖IV。
解题思路:DP,借用状态机模型构建状态的转移过程和初始化。
状态定义f[i][j][0]
:前i天交易了j次,未持有股票时的最大价值。
状态定义f[i][j][1]
:前i天,正在进行第j次交易(即已经买入了股票,等待卖出中),且持有股票的最大价值。
状态转移,
f[i][j][0] = max(f[i-1][j][0], f[i-1][j][1] + w[i])
f[i][j][1] = max(f[i-1][j][1], f[i-1][j-1][0] - w[i])
初始化过程如下,
f[i][j][0] = f[i][j][1] = -0x3f3f3f3f
f[i][0][0] = 0
最终答案,f[n][j][0]
。
C++代码如下,
#include <iostream>
using namespace std;
const int N = 100010, M = 110;
int n, m;
int w[N];
int f[N][M][2];
int main() {
cin >> n >> m;
for (int i = 1; i <= n; ++i) cin >> w[i];
//初始化
for (int i = 0; i <= n; ++i) {
for (int j = 0; j <= m; ++j) {
f[i][j][0] = f[i][j][1] = -0x3f3f3f3f;
}
}
for (int i = 0; i <= n; ++i) f[i][0][0] = 0;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
f[i][j][0] = max(f[i-1][j][0], f[i-1][j][1] + w[i]);
f[i][j][1] = max(f[i-1][j][1], f[i-1][j-1][0] - w[i]);
}
}
int res = 0;
for (int j = 0; j <= m; ++j) res = max(res, f[n][j][0]);
cout << res << endl;
return 0;
}
题目3:买卖股票V。
解题思路:DP。
状态定义f[i][0]
:从前i天中选择,且手中无货的最大价值。
状态定义f[i][1]
:从前i天中选择,且处于冷冻期的最大价值。
状态定义f[i][2]
:从前i天中选择,且手中有货的最大价值。
状态转移,
f[i][0] = max(f[i-1][0], f[i-1][1])
f[i][1] = f[i-1][2] + w[i]
f[i][2] = max(f[i-1][2], f[i-1][0] - w[i])
初始化为,
f[i][0] = f[i][1] = f[i][2] = -0x3f3f3f3f
f[0][0] = 0
最终答案,max(f[n][0], f[n][1])
。
C++代码如下,
#include <iostream>
using namespace std;
const int N = 100010;
int n;
int w[N];
int f[N][3];
int main() {
cin >> n;
for (int i = 1; i <= n; ++i) cin >> w[i];
//初始化
for (int i = 0; i <= n; ++i) {
f[i][0] = f[i][1] = f[i][2] = -0x3f3f3f3f;
}
f[0][0] = 0;
//状态转移
for (int i = 1; i <= n; ++i) {
f[i][0] = max(f[i-1][0], f[i-1][1]);
f[i][1] = f[i-1][2] + w[i];
f[i][2] = max(f[i-1][2], f[i-1][0] - w[i]);
}
cout << max(f[n][0], f[n][1]) << endl;
return 0;
}
题目4:设计密码。
思考:暂时没有看懂做法。后续补充。
C++代码如下,
#include <iostream>
#include <cstring>
using namespace std;
const int N = 55, mod = 1e9 + 7;
int n, m;
char str[N];
int f[N][N];
int main() {
cin >> n >> str + 1;
m = strlen(str + 1);
int next[N] = {0};
for (int i = 2, j = 0; i <= n; ++i) {
while (j && str[i] != str[j + 1]) j = next[j];
if (str[i] == str[j + 1]) j++;
next[i] = j;
}
f[0][0] = 1;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
for (char k = 'a'; k <= 'z'; ++k) {
int u = j;
while (u && k != str[u + 1]) u = next[u];
if (k == str[u + 1]) u++;
if (u < m) f[i + 1][u] = (f[i + 1][u] + f[i][j]) % mod;
}
}
}
int res = 0;
for (int i = 0; i < m; ++i) res = (res + f[n][i]) % mod;
cout << res << endl;
return 0;
}