【纪中模拟2019.08.03】【JZOJ1308】取数游戏

题目链接

题意:

  N个正整数围成一圈,规则如下:

•两个玩家轮流取数;
•先手玩家取任意一个数x;
•从第二步开始当前玩家只能取x(上一玩家取的数)相邻的数;
•直到取完所有的数,游戏结束;
•取得较多奇数的玩家获胜。

  保证双方都采取最优策略的同时,计算先手有多少种取法获胜。

  $1\le N\le 10^2,\quad 1\le x\le 10^3$

实现(100分):

  因为笔者不会SG函数,所以如果有绕弯子的描述请谅解。

  分析博弈过程,有$2^n$种形势,按博弈写程序会T。

  考虑DP,貌似取数的过程有后效性,然而这是因为不熟悉环的性质(套路)导致。事实上,当你取走环上一个数,并规定只能操作原数两端的其他数的时候,可以看做把环由某点断开、展平,并规定只能在这个区间的两端取数。所以第二步及以后的所有取数操作都不再具有后效性了,可以区间DP。

  于是我们知道,只能枚举$n$种展开方式,如果能获胜,令答案$+1$。

  定义$f_{i,j}$表示对于区间$[i,j]$(长度$<n$),先手取数比后手多取得奇数的个数,那么有$$f_{i,j}=max\{\,a_i-f_{i+1,j}\,,\,a_j-f_{i,j-1}\,\}$$

  先后手的转换:取相反数。

  注意区间左端点的取值范围:它和区间长度有关。要做全$2n$内的所有区间情况。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define IL inline
using namespace std;
const int N=100;

    int n,a[N*2+3];
    int f[N*2+3][N*2+3];

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);

    for(int i=1;i<=n;i++)
        a[i]&=1;
    for(int i=1;i<=n;i++)
        a[i+n]=a[i];

    for(int i=1;i<=n*2;i++)
        f[i][i]=a[i];

    for(int t=2;t<=n;t++)
        for(int i=1;i+t-1<=n*2;i++){
            int j=i+t-1;
            f[i][j]=max(a[i]-f[i+1][j],a[j]-f[i][j-1]);

        }

    int ans=0;
    for(int i=1;i<=n;i++)
    if(a[i]-f[i+1][i+n-1]>0)
        ans++;

    printf("%d",ans);

    return 0;

}

小结:

  问题多想两步,别一刀砍死,可能有转机。

原文地址:https://www.cnblogs.com/Hansue/p/11295432.html

时间: 2024-08-29 20:59:41

【纪中模拟2019.08.03】【JZOJ1308】取数游戏的相关文章

【纪中模拟2019.08.17】【JZOJ3503】粉刷

题目链接 题意: 给定一个$N\times M$的$01$矩阵,要求覆盖所有$1$的位置,求最小操作次数.一次操作,可以竖着覆盖连续的最多$C$列,或者横着覆盖连续的最多$R$行. $1\le\;N,\;M,\;R,\;C\le\;15$ 分析: 数据范围较小,考虑枚举. 但是不能盲目地同时枚举覆盖行.覆盖列的操作,因为这样的枚举是$O (2^{2N})$的,会$T$. 考虑枚举覆盖行的操作,枚得一种方案之后贪心地计算覆盖列的操作,完成. 总的时间复杂度$O (N^3\times 2^N)$.

【纪中集训2019.08.21】【JZOJ6315】数字

题目链接 题意: 设$s(i)$为将$1\sim i$看做字符串后依次连接形成的串.给定正整数$n$,求最小的$i$使得$n$是$s(i)$的字串.$T$组数据. $n\le 10^{17}, \; t\le 10^4$ 分析: 不能模拟$s(i)$的组成过程来找答案,时间不能承受. 也不能预处理$s(k)$,空间不能承受. 那就只能在$n$上找答案. 以下把数字当成字面量来讨论,更方便. 同时,这里讨论的前缀和后缀不包括本身. 思考一下,答案分为三种: 1.$ans=n$ 2.$n$由$ans

【纪中集训2019.08.20】【JZOJ6310】Global warming

题目链接 题意: 给出一个长度为$n$的序列$\{a_n\}$. 已知一个正整数$x$,你有一次机会指定区间$[l,r]$,令$\forall i\in [l,r],\;a_i=a_i+d\,(|d|\le x)$. 求最大化的最长上升子序列的长度. $1 \le n \le 2 \times 10^5 , \quad 1 \le a_i,x \le 10^9$且均为正整数. 分析: 可以很容易发现三个性质: 性质一:抬升$[l,r]$不优于抬升$[l,n]$,降低$[l,r]$不优于降低$[1

【日常学习】【区间DP+高精】codevs1166 矩阵取数游戏题解

题目来自NOIP2007TG3 如果在考场上我现在已经歇菜了吧 今天一整天的时间全部投在这道题上,收获不小. 先上题目 题目描述 Description [问题描述] 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m 的矩阵,矩阵中的每个元素aij均 为非负整数.游戏规则如下: 1. 每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. 每次取走的各个元素只能是该元素所在行的行首或行尾: 3. 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分= 被取走的元素

矩阵取数游戏

题目描述 Description [问题描述]帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m 的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下:1. 每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素:2. 每次取走的各个元素只能是该元素所在行的行首或行尾:3. 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分= 被取走的元素值*2i,其中i 表示第i 次取数(从1 开始编号):4. 游戏结束总得分为m次取数得分之和.帅帅想请你帮忙写一个程序,对于任意矩

P1005矩阵取数游戏

题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2.每次取走的各个元素只能是该元素所在行的行首或行尾: 3.每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分 = 被取走的元素值*2^i,其中i表示第i次取数(从1开始编号): 4.游戏结束总得分为m次取数得分之和. 帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分. 输入输

NOIP2007 矩阵取数游戏

题目描述 Description [问题描述] 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m 的矩阵,矩阵中的每个元素aij均 为非负整数.游戏规则如下: 1. 每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. 每次取走的各个元素只能是该元素所在行的行首或行尾: 3. 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分= 被取走的元素值*2i, 其中i 表示第i 次取数(从1 开始编号): 4. 游戏结束总得分为m次取数得分之和. 帅帅想请你帮忙写一个

BZOJ 1978 取数游戏(DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1978 题意:给出一个数列a,在其中找出下标依次增大的数,使得任意相邻的两个数的最大公约数大于等于m.找出最多的数字. 思路:f[i]表示前面的数字中最大公约数为i可以找出的最多的数字个数.那么对于当前数字x: 接着更新f: int f[N],a[N]; int n,m; int main() { RD(n,m); int i; FOR1(i,n) RD(a[i]); int j,k;

矩阵取数游戏洛谷p1005

题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2.每次取走的各个元素只能是该元素所在行的行首或行尾: 3.每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分 = 被取走的元素值*2^i,其中i表示第i次取数(从1开始编号): 4.游戏结束总得分为m次取数得分之和. 帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分. 输入输