TYVJ P1075 硬币游戏 Label:dp
背景
描述
游戏开始后,A先取一枚或两枚硬币。如果A取了一枚,那么B可以继续取一枚或两枚;如果A取了两枚,那么B可以取一到四枚硬币。每次都只能从最上面取。每一次,当前取硬币的人都至少取一枚硬币,最多可以取他的对手上一次取硬币数目的两倍。当没有硬币可取的时候,游戏就结束了。
然后,他们就可以用得到的硬币向John买东西,当然,他们游戏的目的就是要尽可能使自己得到的硬币价值更大。现在你的任务是,求出在两个人都想得到更大价值的情况下,游戏结束后,第一个人最多能得到的硬币价值。
输入格式
第2到n+1行: 第 i+1 行代表从上数第i枚硬币的价值。
输出格式
测试样例1
输入
5
1
3
1
7
2
输出
9
备注
translated by pricez
思路集合
解题思路
那么不难发现几个必须枚举的状态
1、对方在上一轮取了几个(这个直接影响我方这回合取的数目)
2、当前还剩多少个可以取
3、我方这回合取了多少个
接着
假设上回合对方拿走了J个后还剩I个可供我们这回合拿取,那么可以推出我们能拿的硬币数的范围在1~2*J之间则可以列出
F[I,J]:=MAX(SUM[I]-F[I-K,K]);(1<=K<=2*J)
其中SUM[I]表示剩下的I个硬币的总面值
K表示我当前这回合拿了多少个
因为双方都是最优的取法来取
所以F[I-K,K]表示的就是对手在我拿走K个硬币还剩下I-K个硬币的情况他最多能取的面值大小
因而SUM[I]-F[I-K,K]表示的意义就是我在剩下的硬币中能取得的最多的面值大小
初始状态是F[0,1~N]=0;
末状态是F[N,1]
理解了上面的方程后
可以看出方程的时间复杂度就是O(N^3)显然会超时
这时候就需要优化
我们观察
F[I,J]的方程与F[I,J-1]的方程
可以发现
F[I,J-1]所枚举的所有状态在F[I,J]时又枚举了一遍,明显这是多余的
可以看出F[I,J]比F[I,J-1]多枚举的只有SUM[I]-F[I-(2*J-1),2*J-1]和SUM[I]-F[I-2*J,2*J]两项
所以方程可以改写成
F[I,J]:=MAX(F[I,J-1],MAX(SUM[I]-F[I-(2*J-1),2*J-1],SUM[I]-F[I-2*J,2*J]));
这样就优化到O(N^2)了
基本调试清楚下就可以AC了
---------------------
其实不需如上优化
第一个方程+单调队列足以AC
我们发现,每一个阶段都由上一个玩家决定的,即别人怎么拿限制了我怎么拿,那么
设状态为f(i, j)表示剩余i个硬币,上次拿了j个硬币,注意,是上一次!
则
f(i, j)=max{sum(1, i)-f(i-k, k)} 1<=k<=2*j
这点可以参照前边一题的dp博弈
sum(1, i)包含了2重意思,即sum(1, i-k), sum(i-k+1, i),前者是之前局面的和,后者是玩家所得的价值
而f(i-k, k)的意思就是根据上一次所拿硬币j限制了我这次拿硬币k,而这个状态就表示我这次拿了k个之后还剩与i-k个,而且是从我这个状态k个限制了它所拿硬币。
然后注意读入是倒序即可
但是这样做状态是n^2,转移n,显然2000的数据tle。
那么我们要优化
我们来看看f(10,1)的情况。

在这里,我们发现f(8,2)和f(8,1)的区别就是比其多了2条路,所以我们完全能想到以下方法。

将 除了自己特有的两条路保留后,另两条路舍去,直接连到f(8,1)的最优解上,这样就能将时间复杂度优化为O(n^2),这样的话,我们的状态转移方程可 以写为f(x,y)=Max{ f(x,y-1),sum[x]-Min{f(x-(2*y-1),2*y-1),f(x-2*y,2*y)} }
附不懂的代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int N,a[],f[][],sum[];
int main(){
// freopen("01.txt","r",stdin);
scanf("%d",&N);
for(int i=N;i>;i--)
scanf("%d",&a[i]);
for(int i=;i<=N;i++)
sum[i]=sum[i-]+a[i]; for(int i=;i<=N;i++)
for(int j=;j<=N;j++){
f[i][j]=f[i][j-];//自己特有的两条路保留,直接连到f(i,j-1)的最优解上
if(i-(j<<)>=)
f[i][j]=max(f[i][j],sum[i]-f[i-(j<<)][j<<]);
if(i-((j<<)-)>=)
f[i][j]=max(f[i][j],sum[i]-f[i-((j<<)-)][(j<<)-]);
}
printf("%d\n",f[N][]);
return ;
}
TYVJ P1075 硬币游戏 Label:dp的更多相关文章
- tyvj P1075 - 硬币游戏 博弈DP
P1075 - 硬币游戏 From price Normal (OI)总时限:10s 内存限制:128MB 代码长度限制:64KB 背景 Background 农民John的牛喜欢玩 ...
- 【BZOJ】2017: [Usaco2009 Nov]硬币游戏(dp+神题+博弈论)
http://www.lydsy.com/JudgeOnline/problem.php?id=2017 这题太神了,我想了一个中午啊 原来是看错题一直没理解题解说的,一直以为题解是错的QAQ “开始 ...
- bzoj 2017: [Usaco2009 Nov]硬币游戏【dp】
废了废了,一个小dp都想不出来 把c数组倒序一下,变成1在最下,设f[i][j]为某一人取完j个之后还剩1~i的硬币,转移的话应该是f[i][j]=max(s[i]-f[i-k][k]),就是1~n的 ...
- BZOJ 4820 [Sdoi2017]硬币游戏 ——期望DP 高斯消元
做法太神了,理解不了. 自己想到的是建出AC自动机然后建出矩阵然后求逆计算,感觉可以过$40%$ 用一个状态$N$表示任意一个位置没有匹配成功的概率和. 每种匹配不成功的情况都是等价的. 然后我们强制 ...
- BZOJ_2017_[Usaco2009 Nov]硬币游戏_博弈论+DP
BZOJ_2017_[Usaco2009 Nov]硬币游戏_博弈论+DP Description 农夫约翰的奶牛喜欢玩硬币游戏,因此他发明了一种称为“Xoinc”的两人硬币游戏. 初始时,一个有N(5 ...
- 【BZOJ4820】[Sdoi2017]硬币游戏 AC自动机+概率DP+高斯消元
[BZOJ4820][Sdoi2017]硬币游戏 Description 周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数多谁胜利.大家纷纷觉得这个游戏非常符合同学们的特色,但只是扔硬 ...
- 4820: [Sdoi2017]硬币游戏
4820: [Sdoi2017]硬币游戏 链接 分析: 期望dp+高斯消元. 首先可以建出AC自动机,Xi表示经过节点i的期望次数,然后高斯消元,这样点的个数太多,复杂度太大.但是AC自动机上末尾节点 ...
- [BZOJ4820]硬币游戏 KMP+高斯消元
4820: [Sdoi2017]硬币游戏 Time Limit: 10 Sec Memory Limit: 128 MB Description 周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的 ...
- [BZOJ2017][Usaco2009 Nov]硬币游戏
Description 农夫约翰的奶牛喜欢玩硬币游戏,因此他发明了一种称为“Xoinc”的两人硬币游戏. 初始时,一个有N(5 <= N <= 2,000)枚硬币的堆栈放在地上,从堆顶数起 ...
随机推荐
- mysql in 子查询 效率慢 优化(转)
mysql in 子查询 效率慢 优化(转) 现在的CMS系统.博客系统.BBS等都喜欢使用标签tag作交叉链接,因此我也尝鲜用了下.但用了后发现我想查询某个tag的文章列表时速度很慢,达到5秒之久! ...
- 细微之处:比较两种CSS清除浮动的兼容
http://www.cnblogs.com/bienfantaisie/archive/2011/05/27/2059597.html 清除浮动是连续浮动元素之后的必备工作,在工作中我做到需要清除浮 ...
- Compare Strings
Compare two strings A and B, determine whether A contains all of the characters in B. The characters ...
- shell脚本去重的几种方法
测试文件 [root@bogon ~]# cat >test jason jason jason fffffjason 按 Ctr + D保存 1.sort -u [root@bogon ~]# ...
- poj 2136 Vertical Histogram 解题报告
题目链接:http://poj.org/problem?id=2136 题意不难理解,就是输入四行字符串(每行字符总数不超过72个),统计26个英文字母的数目,并按柱状图的形式输出.我的思路就是,先用 ...
- springJDBC实现查询方法二
无废话,看代码: @Override public List<Sites> queryAllSites(Pager pager) { String sql = "select * ...
- 【linux】awk的使用
教程来自:http://www.runoob.com/linux/linux-comm-awk.html 教程中的例子很好,可以有助于快速上手awk.但是里面的细节介绍的并不清楚. 问题1:什么时候写 ...
- 分页管理的AJAX实现
bookMgr.jsp <%-- Document : bookMgr.jsp Created on : 2016-11-7, 9:48:21 Author : guanghe --%> ...
- Circle(codevs 3134)
题目描述 Description 在一个圆上,有2*K个不同的结点,我们以这些点为端点,连K条线段,使得每个结点都恰好用一次.在满足这些线段将圆分成最少部分的前提下,请计算有多少种连线的方法 输入描述 ...
- 一、HTML和CSS基础--网页布局--实践--导航条菜单的制作
案例一:导航菜单的制作 垂直菜单