日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

DP 状态机模型 AcWing算法提高课 详解

發布時間:2025/3/19 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 DP 状态机模型 AcWing算法提高课 详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

狀態機模型

AcWing 1049. 大盜阿福

#include <iostream> #include <algorithm> #include <cmath> #include <cstring> #include <string> #include <vector> #include <unordered_map> #include <unordered_set> #include <set> #include <map> #include <stack> #include <queue> #include <deque> #include <ctime> #include <sstream> #define endl '\n' #define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0) #define lowbit(x) (x&-x) using namespace std; const double pi = acos(-1); typedef long long ll; typedef pair<int, int> PII; typedef pair<long, long> PLL;const int N = 1e5 + 10;int w[N]; int f[N][2];int main() {int _; cin >> _;while (_ -- ){int n;cin >> n;for (int i = 1; i <= n; i ++ ) cin >> w[i];// memset(f, 0, sizeof f);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];}cout << max(f[n][0], f[n][1]) << endl;} }

AcWing 1057. 股票買賣 IV (初始化)

  • 本題限制了 總交易的次數,因此不能用貪心
  • 對于第iii購入的股票,當且僅當第j(i<=j)j(i<=j)j(i<=j)天才能賣掉,獲得的利潤wj?wiw_j-w_iwj??wi?,由此可知這是一個線性問題
  • 以當前遞推到的天數,作為線性dp的階段,對于遞推到的第iii天,我們需要記錄的信息有:
  • 1.在完成第iii天的決策后,狀態是持倉還是空倉
  • 2.在第iii天交易完成時,總共完成的完整的交易數(題目規定一次買入加一次賣出才是一場完整交易)
  • 于是,狀態表示f[i,j,k]f[i,j,k]f[i,j,k]表示考慮前iii天的股票,第iii天的持倉空倉狀態是kkk,且完成的完整交易次數是jjj,屬性是maxmaxmax

狀態機模型DP

  • 1.第i天狀態是空倉狀態(i==0),則第i2天產生的行為是賣出行為或者空倉行為
  • 2.第i天狀態是持倉狀態(i==1),則第i天產生的行為是買入行為或者持倉行為

#include <iostream> #include <algorithm> #include <cmath> #include <cstring> #include <string> #include <vector> #include <unordered_map> #include <unordered_set> #include <set> #include <map> #include <stack> #include <queue> #include <deque> #include <ctime> #include <sstream> #define endl '\n' #define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0) #define lowbit(x) (x&-x) using namespace std; const double pi = acos(-1); typedef long long ll; typedef pair<int, int> PII; typedef pair<long, long> PLL;const int N = 1e5 + 10, M = 110;int f[N][M][2]; int w[N];int main() {int n, k;cin >> n >> k;for (int i = 1; i <= n; i ++ ) cin >> w[i];// 注意1memset(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 = 0; j <= k; j ++ ){f[i][j][0] = f[i - 1][j][0];if (j) f[i][j][0] = max(f[i][j][0], f[i - 1][j - 1][1] + w[i]); // 注意2f[i][j][1] = max(f[i - 1][j][1], f[i - 1][j][0] - w[i]);}int res = 0;for (int i = 0; i <= k; i ++ ) res = max(res, f[n][i][0]); // 注意3 最后一天必須是空倉cout << res << endl;return 0; }

AcWing 1058. 股票買賣 V

  • 狀態f[i,j]f[i,j]f[i,j]表示考慮前i天股市,當前第i天的狀態是j的方案,屬性是maxmaxmax
  • 如果第i天是空倉(且非冷凍)狀態(0),則第i-1天是空倉或者即將冷凍 即 f[i,0]=max(f[i?1,0],f[i?1,2])f[i,0]=max(f[i-1,0],f[i-1,2])f[i,0]=max(f[i?1,0],f[i?1,2])
  • 如果第i天是即將冷凍狀態(2),則第i-1天是持倉狀態 即 f[i,2]=f[i?1,1]+w[i]f[i,2]=f[i-1,1]+w[i]f[i,2]=f[i?1,1]+w[i]
  • 如果第i天是持倉狀態(1),則第i-1天是持倉狀態或者空倉 即 f[i,1]=max(f[i?1,1],f[i?1,0]?w[i])f[i,1]=max(f[i-1,1],f[i-1,0]-w[i])f[i,1]=max(f[i?1,1],f[i?1,0]?w[i])
#include <iostream> #include <algorithm> #include <cmath> #include <cstring> #include <string> #include <vector> #include <unordered_map> #include <unordered_set> #include <set> #include <map> #include <stack> #include <queue> #include <deque> #include <ctime> #include <sstream> #define endl '\n' #define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0) #define lowbit(x) (x&-x) using namespace std; const double pi = acos(-1); typedef long long ll; typedef pair<int, int> PII; typedef pair<long, long> PLL;const int N = 1e5 + 10;int w[N]; int f[N][3];int main() {int n;cin >> n;for (int i = 1; i <= n; i ++ ) cin >> w[i];memset(f, -0x3f, sizeof f);f[0][0] = 0;for (int i = 1; i <= n; i ++ ){f[i][0] = max(f[i - 1][0], f[i - 1][2]);f[i][1] = max(f[i - 1][1], f[i - 1][0] - w[i]);f[i][2] = f[i - 1][1] + w[i];}cout << max(f[n][0], f[n][2]) << endl;return 0; }

AcWing 1052. 設計密碼

  • 這題是有∣T∣+1|T|+1T+1個狀態自動機
  • m個點,每個點有26條邊。一個字符串不包含某個字符串,其實是表示在kmp中走不到m這個點,可以把kmp的過程看成狀態機跳的過程(走到最后一個點表示匹配了,我們要不匹配,所以就是走不到最后一個點)的方案數
  • f[i,j]f[i,j]f[i,j]表示當前已經填到了字符串的第i位(一共填n位),j表示走到了kmp中第j個位置。那么狀態數量就有N*M,每個狀態有26種枚舉方式。因此26N226N^226N2。建圖時,M?26M*26M?26(每個狀態有26種選擇)?N*N?N(每個選擇有一個while循環),所以預處理也是26N226N^226N2,因此總的就是26N226N^226N2
#include <iostream> #include <algorithm> #include <cmath> #include <cstring> #include <string> #include <string.h> #include <vector> #include <unordered_map> #include <unordered_set> #include <set> #include <map> #include <stack> #include <queue> #include <deque> #include <ctime> #include <sstream> #define endl '\n' #define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0) #define lowbit(x) (x&-x) using namespace std; const double pi = acos(-1); typedef long long ll; typedef pair<int, int> PII; typedef pair<long, long> PLL;const int N = 55, mod = 1e9 + 7;int n, m; char str[N]; int f[N][N]; int ne[N];int main() {cin >> n >> (str + 1);m = strlen(str + 1);for (int i = 2, j = 0; i <= n; i ++ ){while (j && str[i] != str[j + 1]) j = ne[j];if (str[i] == str[j + 1]) j ++ ;ne[i] = j;}f[0][0] = 1;for (int i = 0; i < n; i ++ ) // 最終串的長度for (int j = 0; j < m; j ++ ) // kmp數組的長度for (char k = 'a'; k <= 'z'; k ++ ) // 當前位置選哪個字母{int u = j; // j需要跳到哪while (u && k != str[u + 1]) u = ne[u];if (k == str[u + 1]) u ++ ;if (u < m) f[i + 1][u] = (f[i + 1][u] + f[i][j]) % mod; // u小于m就表示不匹配,那么是可以走的}int res = 0;for (int i = 0; i < m; i ++ ) res = (res + f[n][i]) % mod; // 累加所有走不到m的狀態cout << res << endl;return 0; }

AcWing 1053. 修復DNA

  • f[i,j]f[i,j]f[i,j]表示前i個字母,當前走到了ac自動機中第j個位置的所有的操作方案中最少修改的字母數量
  • 建trie時要在所有結尾的地方打一個標記,然后再將trie建成ac自動機。所有打上標記的點應該是完全避開的
#include <iostream> #include <algorithm> #include <cmath> #include <cstring> #include <string> #include <string.h> #include <vector> #include <unordered_map> #include <unordered_set> #include <set> #include <map> #include <stack> #include <queue> #include <deque> #include <ctime> #include <sstream> #define endl '\n' #define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0) #define lowbit(x) (x&-x) using namespace std; const double pi = acos(-1); typedef long long ll; typedef pair<int, int> PII; typedef pair<long, long> PLL;const int N = 1010;int n, m; int tr[N][4], dar[N], idx; int q[N], ne[N]; char str[N];int f[N][N];int get(char c) {if (c == 'A') return 0;if (c == 'T') return 1;if (c == 'G') return 2;return 3; }void insert() {int p = 0;for (int i = 0; str[i]; i ++ ){int t = get(str[i]);if (tr[p][t] == 0) tr[p][t] = ++ idx;p = tr[p][t];}dar[p] = 1; }void build() {int hh = 0, tt = -1;for (int i = 0; i < 4; i ++ )if (tr[0][i])q[ ++ tt] = tr[0][i];while (hh <= tt){int t = q[hh ++ ];for (int i = 0; i < 4; i ++ ){int p = tr[t][i];if (!p) tr[t][i] = tr[ne[t]][i];else{ne[p] = tr[ne[t]][i];q[ ++ tt] = p;dar[p] |= dar[ne[p]];}}} }int main() {int T = 1;while (cin >> n, n){memset(tr, 0, sizeof tr);memset(dar, 0, sizeof dar);memset(ne, 0, sizeof ne);idx = 0;for (int i = 0; i < n; i ++ ){cin >> str;insert();}build();cin >> (str + 1);m = strlen(str + 1);memset(f, 0x3f, sizeof f);f[0][0] = 0;for (int i = 0; i < m; i ++ )for (int j = 0; j <= idx; j ++ )for (int k = 0; k < 4; k ++ ){int t = get(str[i + 1]) != k;int p = tr[j][k];if (!dar[p]) f[i + 1][p] = min(f[i + 1][p], f[i][j] + t);}int res = 0x3f3f3f3f;for (int i = 0; i <= idx; i ++ ) res = min(res, f[m][i]);if (res == 0x3f3f3f3f) res = -1;printf("Case %d: %d\n", T ++ , res);} }

總結

以上是生活随笔為你收集整理的DP 状态机模型 AcWing算法提高课 详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。