有一个长度为n的序列,Alice和Bob在玩游戏。Bob先手掌握决策权。
他们从左向右扫整个序列,在任意时刻,拥有决策权的人有如下两个选择:
-
将当前的数加到自己的得分中,并将决策权给对方,对方将获得下一个数的决策权
-
将当前的数加到对方的得分中,并将决策权保留给自己,自己将获得下一个数的决策权
假定他们都使用最优策略,求他们最后分别能获得多少分
Solution
考虑到无后效性,令 (f[i][0/1]) 表示 0/1 处理完了前 (i) 个数,先手和后手得分的差
转移即枚举上一次的位置
(f[i][1]=max(f[j][0] - a[j+1] - a[j+2] - ... +a[i]))
(f[i][0]=min(f[j][1] + a[j+1] + a[j+2] + ... -a[i]))
换个思路,记 (f[i]) 为从 (i) 开始往后选,能获得的最大收益,我们可以来决策每个位置是否翻面
(f[i]=max(f[i+1], s[i]-f[i+1]))
其中 (s[i]) 是后缀和
#include <bits/stdc++.h>
using namespace std;
const int N = 105;
int n,f[N],s[N],a[N];
int main() {
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=n;i;--i) s[i]=s[i+1]+a[i];
for(int i=n;i;--i) f[i]=max(f[i+1],s[i]-f[i+1]);
cout<<s[1]-f[1]<<" "<<f[1];
}