TZOJ 2965 A Coin Game(DP)

时间:2019-10-16
本文章向大家介绍TZOJ 2965 A Coin Game(DP),主要包括TZOJ 2965 A Coin Game(DP)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

描述

Farmer John's cows like to play coin games so FJ has invented with a new two-player coin game called Xoinc for them.

Initially a stack of N (5 ≤ N ≤ 2,000) coins sits on the ground; coin i from the top has integer value Ci (1 ≤ Ci ≤ 100,000).

The first player starts the game by taking the top one or two coins (C1 and maybe C2) from the stack. If the first player takes just the top coin, the second player may take the following one or two coins in the next turn. If the first player takes two coins then the second player may take the top one, two, three or four coins from the stack. In each turn, the current player must take at least one coin and at most two times the amount of coins last taken by the opposing player. The game is over when there are no more coins to take.

Afterwards, they can use the value of the coins they have taken from the stack to buy treats from FJ, so naturally, their purpose in the game is to maximize the total value of the coins they take. Assuming the second player plays optimally to maximize his own winnings, what is the highest total value that the first player can have when the game is over?

输入

* Line 1: A single integer: N

* Lines 2..N+1: Line i+1 contains a single integer: Ci

输出

* Line 1: A single integer representing the maximum value that can be made by the first player.

样例输入

5
1
3
1
7
2

样例输出

9

题意

有两个人n枚硬币,A先手可以取1-2个,B最多可以取A*2个,问A的最大总价值。

题解

dp[i][j]表示剩下1-i,上个人取了j枚的最大总价值。

那么答案显然是dp[n][1],表示剩下1-n,上个人取了1枚(虚的),那么先手就可以取1枚或者2枚。

O(n^3)的转移dp[i][j]=max(sum[i]-dp[i-k][k])(1<=k<=2*j)。

易得dp[i][j-1]=max(sum[i]-dp[i-k][k])(1<=k<=2*j-2)。

两个相差sum[i]-dp[i-2*j][2*j]和sum[i]-dp[i-(2*j-1)][2*j-1]。

所以O(n^3)的转移可以优化一层变成O(n^2)。

dp[i][j]=(dp[i][j-1]或者max(sum[i]-dp[i-k][k])(2*j-1<=k<=2*j))。

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int n,sum[2005],c[2005],dp[2005][2005];
 5 int main()
 6 {
 7     scanf("%d",&n);
 8     for(int i=n;i>=1;i--)scanf("%d",&c[i]);
 9     for(int i=1;i<=n;i++)sum[i]=sum[i-1]+c[i];
10     for(int i=1;i<=n;i++)
11     {
12         for(int j=1;j<=n;j++)
13         {
14             dp[i][j]=dp[i][j-1];
15             int k=2*j-1;
16             if(k<=i)dp[i][j]=max(dp[i][j],sum[i]-dp[i-k][k]);
17             k++;
18             if(k<=i)dp[i][j]=max(dp[i][j],sum[i]-dp[i-k][k]);
19         }
20         for(int j=1;j<=n;j++)
21             printf("%d ",dp[i][j]);
22         printf("\n");
23     }
24         
25     printf("%d\n",dp[n][1]);
26     return 0;
27 }

原文地址:https://www.cnblogs.com/taozi1115402474/p/11688278.html