bzoj 2017 [Usaco2009 Nov]硬币游戏 动态规划

[Usaco2009 Nov]硬币游戏

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 431  Solved: 240
[Submit][Status][Discuss]

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

5
1
3
1
7
2

Sample Output

9

HINT

 

样例说明:第1个玩家先取走第1枚,第2个玩家取第2枚;第1个取走第3,4两枚,第2个玩家取走最后1枚。

 

Source

 
题解:
  dp[i,j]:i,j,
  ans=dp[n,1]
  转移
    dp[i,j]=max{sum[i]dp[ik,k]}     (1kmin(2j,i)) 
    dp[i,j]=sum[i]max{dp[ik,k]}     (1kmin(2j,i)) 
    dp[i,j1]=sum[i]max{dp[ik,k]}     (1kmin(2j2,i)) 
 1 #include<cstring>
 2 #include<cmath>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cstdio>
 6 
 7 #define N 2007
 8 #define inf 1000000007
 9 #define ll long long
10 using namespace std;
11 inline int read()
12 {
13     int x=0,f=1;char ch=getchar();
14     while(ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
15     while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
16     return x*f;
17 }
18 
19 int n;
20 int c[N],sum[N],dp[N][N];
21 
22 int main()
23 {
24     n=read();
25     for (int i=n;i;i--) c[i]=read();
26     for (int i=1;i<=n;i++) sum[i]=sum[i-1]+c[i];
27     for (int i=1;i<=n;i++)
28     {
29         int mn=inf;
30         for (int j=1;j<=n;j++)
31         {
32             int t=min(j*2,i);
33             mn=min(mn,dp[i-t][t]);
34             t=min(j*2-1,i);
35             mn=min(mn,dp[i-t][t]);
36             dp[i][j]=sum[i]-mn;
37         }
38     }
39     printf("%d",dp[n][1]);
40 }

 

posted @ 2018-01-03 16:42  Kaiser-  阅读(143)  评论(0编辑  收藏  举报