能把不一样的状态之间的关系使用状态机来表示,就可使用状态机模型来处理,不一样的状态之间有前后的时序。c++
acwing1049大盗阿福
题意: 阿福是一名经验丰富的大盗。趁着月黑风高,阿福打算今晚洗劫一条街上的店铺。
这条街上一共有 N 家店铺,每家店中都有一些现金。
阿福事先调查得知,只有当他同时洗劫了两家相邻的店铺时,街上的报警系统才会启动,而后警察就会蜂拥而至。
做为一贯谨慎做案的大盗,阿福不肯意冒着被警察追捕的风险行窃。
他想知道,在不惊动警察的状况下,他今晚最多能够获得多少现金?
题解:
记f[i][0]:选择第i家店铺,可是不抢劫;f[i][1]:选择第i家店铺,进行抢劫
能够获得的状态机转移方程为:
f[i][0] = max(f[i - 1][0], f[i - 1][1])
f[i][1] = f[i - 1][0] + w[i]
边界状态为f[0][0] = 0, f[0][1] = -inf
代码:算法
#include<bits/stdc++.h> using namespace std; int const N = 1e5 + 10; int f[N][2]; int t, n; int w[N]; int main() { cin >> t; while (t--) { /* code */ cin >> n; for (int i = 1; i <= n; ++i ) scanf("%d", &w[i]); memset(f, 0, sizeof f); f[0][0] = 0, f[0][1] = 0xcf; 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]; } printf("%d\n", max(f[n][0], f[n][1])); } return 0; }
acwing1057股票买卖IV
题意: 给定一个长度为 N 的数组,数组中的第 i 个数字表示一个给定股票在第 i 天的价格。设计一个算法来计算你所能获取的最大利润,你最多能够完成 k 笔交易。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉以前的股票)。一次买入卖出合为一笔交易。
题解:
0表示无,1表示有,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][0][0]=0,其余不合法
代码:数组
#include<bits/stdc++.h> using namespace std; int n, k; int const N = 1e5 + 10; int f[N][110][2]; int w[N]; int main() { cin >> n >> k; for (int i = 1; i <= n; ++i) scanf("%d", &w[i]); memset(f, -0x3f, sizeof f); for (int i = 0; i <= n; ++i) f[i][0][0] = 0; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= k; ++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 i = 0; i <= k; ++i) res = max(res, f[n][i][0]); cout << res << endl; return 0; }
acwing1058 股票买卖 V
题意: 给定一个长度为 N 的数组,数组中的第 i 个数字表示一个给定股票在第 i 天的价格。设计一个算法计算出最大利润。在知足如下约束条件下,你能够尽量地完成更多的交易(屡次买卖一支股票):
* 你不能同时参与多笔交易(你必须在再次购买前出售掉以前的股票)。
* 卖出股票后,你没法在次日买入股票 (即冷冻期为 1 天)。
题解:
f[i][0]处理第i次物品时,有货;f[i][1]处理第i次物品时,无货第一天;f[i][2]处理第i次物品时,无货次日
f[i][0] = max(f[i - 1][0], f[i - 1][2] - w[i]);
f[i][1] = f[i - 1][0] + w[i];
f[i][2] = max(f[i - 1][2], f[i - 1][1]);
代码:spa
#include<bits/stdc++.h> using namespace std; const int N = 100010, INF = 0x3f3f3f3f; int n; int w[N]; int f[N][3]; int main() { scanf("%d", &n); for (int i = 1; i <= n; i ++ ) scanf("%d", &w[i]); f[0][0] = f[0][1] = -INF, f[0][2] = 0; for (int i = 1; i <= n; i ++ ) { f[i][0] = max(f[i - 1][0], f[i - 1][2] - w[i]); f[i][1] = f[i - 1][0] + w[i]; f[i][2] = max(f[i - 1][2], f[i - 1][1]); } printf("%d\n", max(f[n][1], f[n][2])); return 0; }