AcWing 1049. 大盗阿福

题目链接

大盗阿福

思路一 线性dp

  • 设置状态\(f[i]\)表示前\(i\)家店铺所能够拿到的最多金额,最后\(f[n-1]\)\(f[n]\)取最大值即可
  • 状态转移:因为不能相邻,所以\(f[i]\)\(f[i-2]\)相关,同时也和\(f[i-1]\)去掉第\(i-1\)家店铺金额相关,也是取大值

代码

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 100005;
int n,a[maxn],f[maxn];
int main() {
    #ifdef ONLINE_JUDGE
    #else
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif // ONLINE_JUDGE
    int T;
    cin >> T;
    while(T--) {
        memset(a,0,sizeof(a));
        memset(f,0,sizeof(f));
        cin >> n;
        for(int i = 1; i <= n; ++i) cin >> a[i];
        f[1] = a[1];
        f[2] = max(a[1], a[2]);
        for(int i = 3; i <= n; ++i) {
            f[i] = max(f[i - 1] - a[i - 1], f[i - 2]) + a[i];
        }
        int res = max(f[n], f[n - 1]);
        cout << res << endl;
    }
    return 0;
}

思路二 状态机模型

  • 用0表示未选取状态,1表示选取状态,有以下状态变化
    • f[i][0]->f[i+1][0] //第\(i\)个店铺不选->第\(i+1\)个店铺也不选
    • f[i][0]->f[i+1][1] //第\(i\)个店铺不选->第\(i+1\)个店铺选
    • f[i][1]->f[i+1][0] //第\(i\)个店铺选->第\(i+1\)个店铺不选
    • f[i][1]->f[i+1][1] //第\(i\)个店铺选->第\(i+1\)个店铺也选,该状态排除,因为不能连续两个相邻店铺都选
  • 最后考虑\(f[n][0]\)\(f[n][1]\)的较大值即可

代码

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 100005;
int f[maxn][2], w[maxn];
int main() {
    #ifdef ONLINE_JUDGE
    #else
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif // ONLINE_JUDGE
    int t;
    cin >> t;
    while (t--) {
        int n;
        cin >> n;
        for(int i = 1; i <= n; ++i) cin >> w[i];
        f[1][0] = 0;
        f[1][1] = w[1];
        for(int i = 2; 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;
    }
    return 0;
}
posted @ 2022-06-01 17:14  lemonsbiscuit  阅读(40)  评论(0编辑  收藏  举报