题目链接
大盗阿福
思路一 线性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;
}