AcWing 1049. 大盜阿福 【 動態規劃(狀態機) 】 題解

林深時不見鹿發表於2020-11-29

1.題目

阿福是一名經驗豐富的大盜。趁著月黑風高,阿福打算今晚洗劫一條街上的店鋪。

這條街上一共有 N 家店鋪,每家店中都有一些現金。

阿福事先調查得知,只有當他同時洗劫了兩家相鄰的店鋪時,街上的報警系統才會啟動,然後警察就會蜂擁而至。

作為一向謹慎作案的大盜,阿福不願意冒著被警察追捕的風險行竊。

他想知道,在不驚動警察的情況下,他今晚最多可以得到多少現金?

輸入格式
輸入的第一行是一個整數 T,表示一共有 T 組資料。

接下來的每組資料,第一行是一個整數 N ,表示一共有 N 家店鋪。

第二行是 N 個被空格分開的正整數,表示每一家店鋪中的現金數量。

每家店鋪中的現金數量均不超過1000。

輸出格式
對於每組資料,輸出一行。

該行包含一個整數,表示阿福在不驚動警察的情況下可以得到的現金數量。

資料範圍
1≤T≤50,
1≤N≤105
輸入樣例:
2
3
1 8 2
4
10 7 6 14
輸出樣例:
8
24
樣例解釋
對於第一組樣例,阿福選擇第2家店鋪行竊,獲得的現金數量為8。

對於第二組樣例,阿福選擇第1和4家店鋪行竊,獲得的現金數量為10+14=24。

2.思路

在這裡插入圖片描述
在這裡插入圖片描述
狀態表示:
我們設f[i][1]表示選擇當前商鋪i的最優值,同理f[i][0]表示不選擇當前商鋪i的最優值。
對於f[i][0]:
不搶第 i 個店鋪可以由不搶第i-1個商店,或者搶第i-1個商店轉移過來。
轉移方程為:
f[i][0]=max(f[i-1][0],f[i-1][1])
對於f[i][1]:
由於不能搶相鄰的,所以搶第i個店鋪時一定不能搶第i−1個店鋪,因此搶劫第i個商店只能從不搶第i-1個店轉移過來。
f[i][1]=f[i-1][0]+w[i]

3.程式碼

/*
狀態機模型
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e5+10,INF=1e9;
int w[N],f[N][2];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        f[0][0]=0,f[0][1]=-INF;  //初始化
        for(int i=1;i<=n;i++) scanf("%d",&w[i]);
        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;
}

相關文章