【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. 详细解读Spark的数据分析引擎:Spark SQL

    一.spark SQL:类似于Hive,是一种数据分析引擎 什么是spark SQL? spark SQL只能处理结构化数据 底层依赖RDD,把sql语句转换成一个个RDD,运行在不同的worker上 ...

  2. linux_vim

    今天稍微学习以下vim 学习的一些课件: 1. 2. 3. 4. 5.

  3. Django Rest Framework源码剖析(一)-----认证

    一.简介 Django REST Framework(简称DRF),是一个用于构建Web API的强大且灵活的工具包. 先说说REST:REST是一种Web API设计标准,是目前比较成熟的一套互联网 ...

  4. 20155310 Exp6 信息收集与漏洞扫描

    20155310 Exp6 信息收集与漏洞扫描 基础问题回答 1.哪些组织负责DNS,IP的管理. 顶级的管理者是Internet Corporation for Assigned Names and ...

  5. python 回溯法 子集树模板 系列 —— 3、0-1背包问题

    问题 给定N个物品和一个背包.物品i的重量是Wi,其价值位Vi ,背包的容量为C.问应该如何选择装入背包的物品,使得放入背包的物品的总价值为最大? 分析 显然,放入背包的物品,是N个物品的所有子集的其 ...

  6. 使用nginx很卡之strace命令

    一.strace命令常用参数 strace -tt -T -v -f -e trace= -p -tt 在每行输出的前面,显示毫秒级别的时间 -T 显示每次系统调用所花费的时间 -v 对于某些相关调用 ...

  7. win7笔记本VirtualBox安装黑苹果MacOS 10.13

    环境 时间:2018.04.09,没有指明时间的教程都是耍流氓 笔记本:某州优雅A460P-i7G D2,4G内存,Intel Core i7-2670QM四核八线程(老笔记本勉强能用),ssd硬盘, ...

  8. Join 和 Apply 用法全解

    在关系型数据库系统中,为了满足第三范式(3NF),需要将满足“传递依赖”的表分离成单独的表,通过Join 子句将相关表进行连接,Join子句共有三种类型:外连接,内连接,交叉连接:外连接分为:left ...

  9. 【ORACLE】Win2008R2修改oracle数据库实例名

    需求说明:要求将windows平台的数据库实例名由orcl改为haha 参考: https://www.cnblogs.com/junnor/archive/2013/03/05/2945245.ht ...

  10. 吉他软件Guitar Pro播放无声音的解决方法

    系统环境:适用于Windows操作系统和macOS的Guitar Pro . 问题表现:已成功安装Guitar Pro ,但用Guitar Pro 播放时没有任何声音或播放失真. 解决方案:首先确保安 ...