CF201C 题解
题目大意
这个游戏包含
游戏的过程是这样的:
-
首先找到一个起始的平台。
-
如果两边有桥,可以选择一边行走。如果走过一座桥之后走过的次数已经超过了
a_i ,这座桥就会断裂。 -
如果当前所在的平台已经没有桥连接到另外任意一个平台,游戏结束。
在游戏结束时会计算分数。分数即为走过桥的次数。
请问最大的分数是多少?
题目分析
我们将第
所以可以定义
首先我们思考
我们的答案就因该为
而因为不回第
我们是要不回来的,所以我们应该在这座桥中尽量多走几次,所以走的次数必须是奇数。
在 c++ 中我们可以这样写:
dp[i][0] = max(dp[i - 1][0], dp[i - 1][1]) + ((a[i - 1] & 1) ? a[i - 1] : (a[i - 1] - 1));
接着我们考虑
为了拿到最大分数,我们要像之前一样,因为要回去,我们需要经过偶数次桥。如果当前桥能走的次数是奇数,那就只能浪费一次机会达到能回来的目的。
在 c++ 中我们可以这样写:
dp[i][1] = dp[i - 1][1] + ((a[i - 1] & 1) ? (a[i - 1] - 1) : a[i - 1]);
而
Code
#include <cstdio>
#include <iostream>
#define ll long long
using namespace std;
const int MAXN = 1e5 + 5;
ll ans;
ll n, a[MAXN], dp[MAXN][4];
int main() {
scanf("%lld", &n);
for(int i = 1; i < n; i++)
scanf("%lld", &a[i]);
for(int i = 2; i <= n; i++) {
dp[i][0] = max(dp[i - 1][0], dp[i - 1][1]) + ((a[i - 1] & 1) ? a[i - 1] : (a[i - 1] - 1));
if(a[i - 1] > 1)
dp[i][1] = dp[i - 1][1] + ((a[i - 1] & 1) ? (a[i - 1] - 1) : a[i - 1]);
}
for(int i = n - 1; i >= 1; i--) {
dp[i][2] = max(dp[i + 1][2], dp[i + 1][3]) + ((a[i] & 1) ? a[i] : (a[i] - 1));
if(a[i] > 1)
dp[i][3] = dp[i + 1][3] + ((a[i] & 1) ? (a[i] - 1) : a[i]);
}
for(int i = 1; i <= n; i++)
ans = max(ans, max(dp[i][0] + dp[i][3], dp[i][1] + dp[i][2]));
printf("%lld", ans);
return 0;
}