【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";
}

 

posted @ 2016-03-06 11:32  mengyue  阅读(406)  评论(0编辑  收藏  举报