USACO 2010 Dec Silver 2.Treasure Chest 简单博弈 DP

来源:互联网 发布:美工钢笔书法 编辑:程序博客网 时间:2024/05/24 06:42

Description

Bessie and Bonnie have found a treasure chest full of marvelous gold coins! Being cows, though, they can't just walk into a store and buy stuff, so instead they decide to have some fun with the coins.

The N (1 <= N <= 5,000) coins, each with some value C_i (1 <= C_i <= 5,000) are placed in a straight line. Bessie and Bonnie take turns, and for each cow's turn, she takes exactly one coin off of either the left end or the right end of the line. The game ends when there are no coins left.
Bessie and Bonnie are each trying to get as much wealth as possible for themselves. Bessie goes first. Help her figure out the maximum value she can win, assuming that both cows play optimally.

Consider a game in which four coins are lined up with these values:

               30   25   10   35

Consider this game sequence:

 

                           Bessie    Bonnie       New CoinPlayer   Side   CoinValue   Total     Total         LineBessie   Right     35        35         0       30  25  10Bonnie   Left      30        35        30         25  10Bessie   Left      25        60        30           10Bonnie   Right     10        60        40           --

This is the best game Bessie can play.

Input
* Line 1: A single integer: N

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

Output
* Line 1: A single integer, which is the greatest total value Bessie can win if both cows play optimally.

Sample Input
4
30
25
10
35

Sample Output
60

题意:一排硬币,两人轮流从左端或右端取一枚硬币,每个硬币都有一定价值,问先手能获得的最大总价值。

最近有点喜欢上这种简单博弈论(或是DP)了呢~

设f[j][i]表示还剩i枚硬币,就是从j到j+i-1这段区间的硬币,由于是两个人轮流取,所以i可以简化为i&1,很容易得到状态转移方程:

f[j][i&1]=sum[i+j-1]-sum[j-1]-min(f[j+1][i&1^1],f[j][i&1^1])

也就是用从j到i+j-2这段区间和j+1到i+j-1这段区间取更新j到i+j-1这段区间,最后答案就是f[1][n&1]

代码:

#include<stdio.h>int s[5010],f[5010][2];int n;int min(int x,int y){return x<y?x:y;}int main(){scanf("%d",&n);int i,j,c;for(i=1;i<=n;i++){scanf("%d",&c);s[i]=s[i-1]+c;}for(i=1;i<=n;i++){for(j=1;j<=n-i+1;j++){f[j][i&1]=s[i+j-1]-s[j-1]-min(f[j+1][i&1^1],f[j][i&1^1]);}}printf("%d",f[1][n&1]);return 0;}


 

0 0