您的位置:首页 > 其它

[Wikioi 1037]取数游戏

2014-05-15 21:47 183 查看

题目描述 Description

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

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

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

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

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

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

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



输入描述 Input Description

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

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

输出描述 Output Description

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

样例输入 Sample Input

样例1:

4

2 5 3 0

样例2:

3

0 0 0

样例输出 Sample Output

样例1:

YES

样例2:

NO

数据范围及提示 Data Size & Hint

如描述
题目思路

这个题根本就不是WIKI上标的DP题,而是一道纯粹的模拟题,根据输入数据特点,需要断环为链,再求解,断环为链过程如下图所示



可以使用两个数组linea lineb保存顺时针、逆时针方向的两种反方向的链(如下面代码所示),也可以只用一个数组保存,数组的中点就是出发点,从顺时针、逆时针两个方向寻找答案。

然后就是求解了,要想第一个赢,就得以奇数步到达其中一个边权为0的点(想一想,为什么),由于是第一个玩这个游戏,硬币走奇数步到这个点的人才是自己,而对手要走偶数步,而根据题意可以看出,要想使硬币的两边边权都为0,就必须让硬币到达只有一边边权为0的点,再对另一边边权清零,又为了在最短步数内到达这样一个点,硬币应该始终沿同一方向移动(每次减少与运动方向相反的边的边权)。

下面是代码

#include <stdio.h>
int n,linea[50],lineb[50]; //linea、lineb=保存环的数组
int main()
{
int i,j,k,stepa=0,stepb=0; //stepa=逆时针走的步数,stepb=顺时针走的步数
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&linea[i]);//读入环
for(i=n;i>=1;i--)
lineb[n-i+1]=linea[i];//断环为链
for(i=1;i<=n;i++)
{
if(linea[i]==0) break;
stepa++;
}
for(i=1;i<=n;i++)
{
if(lineb[i]==0) break;
stepb++;
}
if(stepa%2==1||stepb%2==1) printf("YES\n");
else printf("NO\n");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: