博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[USACO09NOV]硬币的游戏A Coin Game
阅读量:5119 次
发布时间:2019-06-13

本文共 3216 字,大约阅读时间需要 10 分钟。

题目描述

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).


不是吧我现在连奶牛题都写不动了我是不是药丸啊

\(sum[i]\)表示还剩下i枚硬币的和

\(f[i][j]\)表示还剩i枚硬币上一次选了j个的最大值

所以这一次的取值范围是\(1 - j*2\)

所以可以从\(i - 1 ~i - j*2\)转移

式子大概长这样\(f[i][j] = max(f[i][j] , sum[i] - f[i - k][k])\)

因为是两人博弈,只有第一个人取得对答案有贡献

所以更新该状态的时候答案应该是ta这次选取的一段区间的答案加上上一次ta自己取硬币的时候的答案

所以要用\(sum[i] - f[i - k][k]\)来更新答案(因为这样上一次自己选的贡献在这一次也可以加上了)

然后这样DP是O(n^3)的

但是有很多的状态冗余

所以我们只需要利用f[i][j-1]的结果

然后再与j-1更新不到的\(i-(j*2-1)\)\(i-(j*2)\)这两个位置取个max就行了

#include
#include
const int M = 4005 ;using namespace std ;inline int read() { char c = getchar() ; int x = 0 , w = 1 ; while(c>'9'||c<'0') { if(c=='-') w = -1 ; c = getchar() ; } while(c>='0'&&c<='9') { x = x*10+c-'0' ; c = getchar() ; } return x*w ;}int n , val[M] , sum[M] ;int f[M][M] ;int main() { n = read() ; for(int i = n ; i >=1 ; i --) val[i] = read() ; for(int i = 1 ; i <= n ; i ++) sum[i] = sum[i - 1] + val[i] ; for(int i = 1 ; i <= n ; i ++) for(int j = 1 ; j <= n ; j ++) { f[i][j] = f[i][j - 1] ; if((j<<1) - 1 <= i) f[i][j] = max(f[i][j] , sum[i] - f[i - (j<<1) + 1][(j<<1) - 1]) ; if((j<<1) <= i) f[i][j] = max(f[i][j] , sum[i] - f[i - (j<<1)][j<<1]) ; } printf("%d\n",f[n][1]) ; return 0 ;}

转载于:https://www.cnblogs.com/beretty/p/9577423.html

你可能感兴趣的文章
关闭Android/iPhone浏览器自动识别数字为电话号码
查看>>
CPU 用户时间 系统时间(转载)
查看>>
Leetcode: Sliding Window Median
查看>>
C++实验2
查看>>
Linux安装Apache报错:Cannot find a valid baseurl for repo: base/7/x86_64解决方案
查看>>
sass03 变量、样式导入
查看>>
node09---中间件
查看>>
洛谷 P1379 八数码难题
查看>>
express 4.x req.query(get方式) req.body(post方式) 接收浏览器发送过来的数据
查看>>
学习路径的相似性--第009期博文
查看>>
python获取当前目录路径和上级路径
查看>>
大孩子维生素 Vita-Big-Kids 180 Capsules
查看>>
基于移动端的问答系统--需求分析与原型设计
查看>>
一次生产 CPU 100% 排查优化实践
查看>>
Java 原型模式(克隆模式)
查看>>
tab选项卡在鼠标经过时实现切换延迟
查看>>
工厂方法
查看>>
aop 日志统一处理
查看>>
ddns+ros(routeros)+centos7.6+nginx+php+dnspod
查看>>
bootstrap对HTML标签的默认样式有哪些修改?
查看>>