码迷,mamicode.com
首页 > 其他好文 > 详细

hdu2176(堆)

时间:2017-10-20 20:05:39      阅读:124      评论:0      收藏:0      [点我收藏+]

标签:cin   尼姆博弈   space   比较   break   输出   操作   输入   ret   

这道题我题意都看了好一会,原谅我基础不扎实。

题意:从输入的数据中选择其中一个,分成两个数,将分成的第二个数与其他数相异或(“异或”运算符(^)相同为0,不同为1。0^0=0,1^0=1,1^1=0),若最终结果为1则输出Yes。将所有石堆的数目,进行异或操作,如果结果为0,则先取者负。如果不为0,则先取者胜,且将异或结果与各堆数目进行异或,结果比原来的数少,则可把原来数目取为异或结呆,使对方处于必败态

看了别人的解题思路:本题和前面写的那题思路是一样的。求出在第i堆取完石子后应该剩下多少个 与其它堆相异或等于0,这是留给对手的是必败态,所以只要求出其它堆的异或值就好了,因为两个相同的数异或以后才是0,。注意:大于10000的数据输入要用scanf啊,不然会超时。

尼姆博弈基本思想:

        两人从n堆物品中取任意个,先取完者胜。

        即将n堆物品的数量异或,得到的值如果为0,则先手败,反之先手胜。

        如果要求先手在胜的条件下,到奇异局势的方法数,则判断异或的值与每一堆原值异或后(结果应该表示该堆没有参加异或时的异或值)与原值比较大小,

如果小于,则方法数加一。且对应的方法后,该堆的数目应变为异或的值与每一堆原值异或的值。

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int main()
{
         int n,m[200000],k,i,s;//n是石子的堆数,数组m存储的是每堆石子的个数
         while(scanf("%d",&n)!=EOF)
         {
                   if(!n)
                   break;
                   s=0;
                   for(i=0;i<n;i++)
                   {
                        cin>>m[i];//根据NIMM博弈的推理策略,应该对每一堆的石子进行异或运算
                        s=s^m[i];//异或操作
                   }
                   if(!s)//s==0(必败态)先取者总是遇见非奇异局势(第一次就是非奇异局势)
                   {
                        printf("No\n");
                   }
                   else
                   {
                        printf("Yes\n");
                        for(i=0;i<n;i++)
                        {
                            k=s^m[i];
                            if(k<m[i])
                             printf("%d %d\n",m[i],k);
                        }
                   }
         }
         return 1;
}

hdu2176(堆)

标签:cin   尼姆博弈   space   比较   break   输出   操作   输入   ret   

原文地址:http://www.cnblogs.com/Emilylice/p/7701110.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!