• 【CodeVS1037】取数游戏


    Description

        有一个有趣得取数游戏。初始时,给出一个环,环上得每条边上都有一个非负整数。这些整数中至少有一个时0。然后,将一枚硬币放在环上得一个节点上。二个玩家就是以这个放硬币得节点为起点开始这个游戏,二人轮流取数,取数得规则如下:

        (1)选择硬币左边或右边得一条边,并且边上得数非0;

        (2)将这条边上的数减至任意一个非负整数(至少要有所减小);

        (3)将硬币移到边的另一端。

        如果轮到一个玩家走,这时硬币左右两边的边上的数值都是0,那么这个玩家就输了。

        如下图所示,描述的时爱丽思和鲍勃两人的对弈过程,其中黑色节点表示硬币所在节点,结果图(d)中,轮到鲍勃走时,硬币两边的边上都是0。所以爱丽思获胜。

        现在你的任务是根据给出的环、边上的数值以及起点(硬币所在位置),判断先走方是否有必胜的策略。

    Input

        输入:第行一个整数N(N<=20),表示环上的节点数。

        第2行N个数,数值不超过30,依次表示N条边上的数值。硬币的起始位置是第一条边与最后一条边之间的节点上。

    Output

        输出:仅1行。若存在必胜策略,则输出‘YES’,否则输出‘NO’。

    Sample Input

    样例1:

    4

    2  5  3  0

    样例2:

    3

    0  0  0

    Sample Output

    样例1:

    YES

    样例2:

    NO

    题解

    其实一开始我是这样想的:先手每次把边减到1,后手只能减到0,到了最后一条边,先手减到0,看一看边中1的数量,就能确定有没有必胜策略,但是由于1的位置不一样,所以。。。(我不会写)

    可以这样做,先把环拆成链,先手有两个方向可以走,取个或。

    先手每次把一条边变成0,可以控制后手的方向,后手也要把他走的下一条边变成0(不然先手还可以从这条路回去,把这条路变成0,后手必输),所以说只要看看最后一条边是不是先手走(就是0之前的边是不是有奇数条)就行了。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int N=25;
    int a[N],b[N];
    int n,c,d;
    int main(){
        scanf("%d",&n);
        for (int i=0;i<n;i++){
            scanf("%d",&a[i]);
            b[n-i-1]=a[i];
        }
        for (c=0;c<n,a[c];c++);
        for (d=0;d<n,b[d];d++);
        if (c%2||d%2)cout<<"YES";else cout<<"NO";
    }
  • 相关阅读:
    swift 学习线路
    常用linux命令
    位运算常用技巧
    我的算法练习
    mac 电脑配置cordova
    swift 2中关键字和解释整理
    C# 类
    C# 循环语句 for循环(嵌套 while 穷举 迭代)
    C# 循环语句 for循环
    C# 分支语句
  • 原文地址:https://www.cnblogs.com/liumengyue/p/5246833.html
Copyright © 2020-2023  润新知