狀態機模型

狀態機模型

1. 算法分析

    能把不一樣的狀態之間的關係使用狀態機來表示,就可使用狀態機模型來處理,不一樣的狀態之間有前後的時序。c++

2. 典型例題

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;
}
相關文章
相關標籤/搜索