洛谷P2964 [USACO09NOV]硬幣的遊戲A Coin Game

Candy?發表於2016-10-23

題目描述

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 C_i (1 <= C_i <= 100,000).

The first player starts the game by taking the top one or two coins (C_1 and maybe C_2) 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?

MEMORY LIMIT: 20 MB

農夫約翰的奶牛喜歡玩硬幣遊戲.

初始時,一個有N枚硬幣的堆疊放在地上,從堆頂數起的第i枚硬幣的幣值 為Ci

開始玩遊戲時,第一個玩家可以從堆頂拿走一枚或兩枚硬幣.如果第一個玩家只拿走堆頂的 一枚硬幣,那麼第二個玩家可以拿走隨後的一枚或兩枚硬幣.如果第一個玩家拿走兩枚硬幣,則第二個玩家可以拿走1,2,3,或4枚硬幣.在每一輪中,當前的玩家至少拿走一枚硬幣,至多拿 走對手上一次所拿硬幣數量的兩倍.當沒有硬幣可拿時,遊戲結束.

兩個玩家都希望拿到最多錢數的硬幣.請問,當遊戲結束時,第一個玩家最多能拿多少錢 呢?

輸入輸出格式

輸入格式:

 

  • Line 1: A single integer: N

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

 

輸出格式:

 

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

 

輸入輸出樣例

輸入樣例#1:
5 
1 
3 
1 
7 
2 
輸出樣例#1:
9 

說明

There are five coins with the values 1, 3, 1, 7, and 2.

The first player starts by taking a single coin (value 1). The opponent takes one coin as well (value 3). The first player takes two more coins (values 1 and 7 -- total 9). The second player gets the leftover coin (value 2-- total 5).、


 

和那道game of sum很想

不過要約束選幾個

f[i][j]表示剩下1到i,上一人選了j個,選手得分的最大值

暴力轉移列舉f[i-k][k],發現f[i][j]只比f[i][j-1]多了兩個轉移,可以優化

關於博弈:f[i][j]是1號先手的話,自然選擇s[i]-f[i-k][k]最大的,這裡面的f[i-k][k]是2號先手

答案就是f[n][1],全剩下,1號先手最大,可以選一個或兩個

 

PS:注意c要倒著

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=2e3+5;
typedef long long ll;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
int n,c[N],s[N],f[N][N];
void dp(){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            f[i][j]=f[i][j-1];
            int k=2*j;
            if(i-k>=0) f[i][j]=max(f[i][j],s[i]-f[i-k][k]);
            k=2*j-1;
            if(i-k>=0) f[i][j]=max(f[i][j],s[i]-f[i-k][k]);
        }
    }
}
int main(){
    n=read();
    for(int i=n;i>=1;i--) c[i]=read();
    for(int i=1;i<=n;i++) s[i]=s[i-1]+c[i];
    dp();
    printf("%d",f[n][1]);
}

 

相關文章