BZOJ_2017_[Usaco2009 Nov]硬币游戏_博弈论+DP
2018-06-24 07:39
525 查看
BZOJ_2017_[Usaco2009 Nov]硬币游戏_博弈论+DP
Description
农夫约翰的奶牛喜欢玩硬币游戏,因此他发明了一种称为“Xoinc”的两人硬币游戏。 初始时,一个有N(5 <= N <= 2,000)枚硬币的堆栈放在地上,从堆顶数起的第I枚硬币的币值为C_i (1 <= C_i <= 100,000)。 开始玩游戏时,第一个玩家可以从堆顶拿走一枚或两枚硬币。如果第一个玩家只拿走堆顶的一枚硬币,那么第二个玩家可以拿走随后的一枚或两枚硬币。如果第一个玩家拿走两枚硬币,则第二个玩家可以拿走1,2,3,或4枚硬币。在每一轮中,当前的玩家至少拿走一枚硬币,至多拿走对手上一次所拿硬币数量的两倍。当没有硬币可拿时,游戏结束。 两个玩家都希望拿到最多钱数的硬币。请问,当游戏结束时,第一个玩家最多能拿多少钱呢?
Input
第1行:1个整数N
第2..N+1行:第i+1行包含1个整数C_i
Output
第1行:1个整数表示第1个玩家能拿走的最大钱数。
Sample Input
51
3
1
7
2
Sample Output
9HINT
样例说明:第1个玩家先取走第1枚,第2个玩家取第2枚;第1个取走第3,4两枚,第2个玩家取走最后1枚。
设f[i][j]表示还剩i枚硬币,上一个人拿了j枚硬币,到最后的最大收益。
先手后手转移相同,f[i][j]=f[i-k][k] (k<=min(2*j,i)),直接DP是$O(n^3)$的。
发现每次j增加时对k的影响只有2*j-1和2*j,再判断一下与i的关系即可。
代码:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define N 2050 int f ,n,s ,a ; int main() { scanf("%d",&n); int i,j; for(i=1;i<=n;i++) { scanf("%d",&a[i]); } for(i=n;i>=1;i--) s[i]=s[i+1]+a[i]; for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { f[i][j]=f[i][j-1]; if(2*j-1<=i) f[i][j]=max(f[i][j],s[n-i+1]-f[i-(2*j-1)][2*j-1]); if(2*j<=i) f[i][j]=max(f[i][j],s[n-i+1]-f[i-2*j][2*j]); } } printf("%d\n",f [1]); }
相关文章推荐
- 【BZOJ】2017: [Usaco2009 Nov]硬币游戏(dp+神题+博弈论)
- BZOJ 2017 [Usaco2009 Nov]硬币游戏
- bzoj 2017: [Usaco2009 Nov]硬币游戏【dp】
- [bzoj 2017] [Usaco2009 Nov]硬币游戏
- [BZOJ2017] [Usaco2009 Nov]硬币游戏
- 【bzoj2017】[Usaco2009 Nov]硬币游戏
- BZOJ:4820: [Sdoi2017]硬币游戏&&BZOJ:1444: [Jsoi2009]有趣的游戏(高斯消元求概率)
- 博弈论+dp——洛谷P2964 [USACO09NOV]硬币的游戏A Coin Game
- bzoj1411 [ZJOI2009]硬币游戏
- bzoj3404 [Usaco2009 Open]Cow Digit Game又见数字游戏
- [BZOJ]1770: [Usaco2009 Nov]lights 燈 高斯消元解xor方程组
- 【bzoj 2017】硬币游戏(DP)
- 【BZOJ】【1770】【Usaco2009 Nov】lights 灯
- [luogu2964][USACO09NOV][硬币的游戏A Coin Game] (博弈+动态规划)
- [BZOJ4820][SDOI2017]硬币游戏(KMP+概率+高斯消元)
- Bzoj1775 [Usaco2009 Dec]Vidgame 电视游戏问题
- 【BZOJ】2018: [Usaco2009 Nov]农场技艺大赛(暴力)
- 洛谷P2964 [USACO09NOV]硬币的游戏A Coin Game
- bzoj 4820: [Sdoi2017]硬币游戏 概率dp+高斯消元+KMP
- BZOJ 1770: [Usaco2009 Nov]lights 燈