Problem Description
有两堆石子,数量任意,可以不同。游戏开始由两个人轮流取石子。游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子;二是可以在两堆中同时取走相同数量的石子。最后把石子全部取完者为胜者。现在给出初始的两堆石子的数目,如果轮到你先取,假设双方都采取最好的策略,问最后你是胜者还是败者。如果你胜,你第1次怎样取子?  
 
Input
输入包含若干行,表示若干种石子的初始情况,其中每一行包含两个非负整数a和b,表示两堆石子的数目,a和b都不大于1,000,000,且a<=b。a=b=0退出。

 
Output
输出也有若干行,如果最后你是败者,则为0,反之,输出1,并输出使你胜的你第1次取石子后剩下的两堆石子的数量x,y,x<=y。如果在任意的一堆中取走石子能胜同时在两堆中同时取走相同数量的石子也能胜,先输出取走相同数量的石子的情况.

 
Sample Input
1 2
5 8
4 7
2 2
0 0
 
Sample Output
0
1
4 7
3 5
0
1
0 0
1 2
 

明显的威佐夫博弈题

其实这道题的关键就在于对威佐夫博弈的理解

首先我们来看这道题所涉及的一部分威佐夫博弈的主要知识点

0,0)、(1,2)、(3,5)、(4,7)、(6,10)、(8,13)、(9,15)、(11,18)、(12,20)。

可以看出,a0=b0=0,ak是未在前面出现过的最小自然数,而 bk= ak + k,

由此我们可以进行一次奇异状态的打表,再枚举所有的状态即可

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <map>
#include <algorithm>
using namespace std; int ans[1000005][2],len;
int hash[2000005];
map<int,map<int,int> > vis; int main()
{
int a,b,i,j,pos;
memset(hash,0,sizeof(hash));
hash[0] = 1;
double k = (sqrt(5)-1.0)/2.0;
ans[0][0] = ans[0][1] = 0;
len = 1;
for(i = 1; i<=1000000; i++)
{
a = i;
j = a*k;
if(a != (int)(j*(1+k)))
j++;
b = a+j;
if(b>1000000)
break;
if(hash[a])
continue;
ans[len][0] = a;
ans[len][1] = b;
hash[a] = hash[b] = 1;
len++;
}
while(~scanf("%d%d",&a,&b),a+b)
{
vis.clear();
if(a>b)
swap(a,b);
j = a*k;
if(a != (int)(j*(1+k)))
j++;
if(a+j == b)
printf("0\n");
else
{
printf("1\n");
if(a == b)//相同可以取完
{
printf("0 0\n");
vis[0][0] = 1;
}
else//我们知道b = a+k,并且可以发现,在奇异状态之中,a,b的差正好就是其位于数组的下标,由此我们可以突出这个状态
{
int k = b-a;
if(b-ans[k][1]==a-ans[k][0]&&b-ans[k][1]>0&&a-ans[k][0]>0)
printf("%d %d\n",ans[k][0],ans[k][1]);
vis[ans[k][0]][ans[k][1]]=1;
}
for(i = 0; i<len; i++)//剩下的就是简单的枚举了,由于奇异状态中,后面的是大的,所以当a在后面出现的话就枚举完了
{
if(a == ans[i][0] && !vis[ans[i][0]][ans[i][1]])
printf("%d %d\n",ans[i][0],ans[i][1]);
if(a == ans[i][1] && !vis[ans[i][0]][ans[i][1]])
{
printf("%d %d\n",ans[i][0],ans[i][1]);
break;
}
}
}
} return 0;
}

HDU2177:取(2堆)石子游戏(威佐夫博弈)的更多相关文章

  1. HDU-2177 取(2堆)石子游戏 (威佐夫博奕)

    Problem Description 有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子:二是可以在两堆中同时取走相同 ...

  2. HDU2177取(2堆)石子游戏---(威佐夫博弈)

    http://acm.hdu.edu.cn/showproblem.php?pid=2177 取(2堆)石子游戏 Time Limit: 3000/1000 MS (Java/Others)    M ...

  3. HDU 2176:取(m堆)石子游戏(Nim博弈)

    取(m堆)石子游戏 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Sub ...

  4. nim3取石子游戏 (威佐夫博弈)

    http://www.cnblogs.com/jackge/archive/2013/04/22/3034968.html 有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有 ...

  5. HDU 1527 取石子游戏(威佐夫博弈)

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission( ...

  6. 洛谷P2252 取石子游戏(威佐夫博弈)

    题目背景 无 题目描述 有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子:二是可以在两堆中同时取走相同数量的石子.最后 ...

  7. hdu1527取石子游戏(威佐夫博弈)

    取石子游戏 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  8. P2252 取石子游戏 威佐夫博弈

    $ \color{#0066ff}{ 题目描述 }$ 有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子:二是可以在两堆 ...

  9. POJ 1067 取石子游戏 威佐夫博弈

    威佐夫博弈(Wythoff Game):有两堆各若干个物品,两个人轮流从某一堆或同时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜. 我们用(ak,bk)(ak ≤ bk ,k= ...

随机推荐

  1. Windows10搭建PHP7开发环境

    原文:Windows10搭建PHP7开发环境 3年前写了一篇<Windows下搭建PHP开发环境>之后就再也没有碰过PHP了,最近新发布了PHP7然后回去看了一下之前写的文章,发现很多配置 ...

  2. 转:Build Your First JavaScript Library

    http://net.tutsplus.com/tutorials/javascript-ajax/build-your-first-javascript-library/ Step 1: Creat ...

  3. python学习链接

    http://www.cnblogs.com/dkblog/archive/2011/06/24/2089026.html 异常处理 http://xiagu1.iteye.com/blog/6195 ...

  4. nagios&pnp4nagios--yum 安装

    一. 环境: 1. centos 6.4 2. 设置hostname 并且安装好apache 3. 关闭selinux及iptables 二. 安装nagios服务器端: 1. rpm -Uvh ht ...

  5. 关于haproxy hdr_reg(host) 的一些解释

    I've recently taken over an environment using HAProxy, and I'm attempting to learn the config and wh ...

  6. jsoi2015 R2——滚粗记

    考完感觉各种绝望溢出胸口,作为百度空间的最后一篇文章了吧 day 0 第二轮在南师附中……不能到外地玩了…… 其实在试机的时候就感觉不大对头,明明说好18:15试机结果拖到18:30…… 还有今年竟然 ...

  7. 4、什么构成了我们Android应用程序?(七大件)

    一.应用程序四大组件 [Activity] Activity是Android应用程序的一个界面,可以通过这个界面查看联系人,打电话戒玩游戏. b. 一个应用程序通常包含多个Activity. c. A ...

  8. POJ 3107-Godfather(树形dp)

    题意: 有n个节点的树,删除一个点,得到的最大联通分支最小,求这样点的集合 分析: dp[i]表示删除i所得最大联通分支,遍历一遍节点即可,该题用vector会超时 #include <map& ...

  9. UESTC 250 windy数(数位DP)

    题意:题意:求区间[A,B]之间的,不含前导0,且相邻两数位之间相差至少为2的正整数有多少个. 分析:dp[i][j]表示,长度为i.以j为结尾的表示的个数,再加一个前导0判断即可 #include ...

  10. HDU 3085 Nightmare Ⅱ 双向BFS

    题意:很好理解,然后注意几点,男的可以一秒走三步,也就是三步以内的都可以,鬼可以穿墙,但是人不可以,鬼是一次走两步 分析:我刚开始男女,鬼BFS三遍,然后最后处理答案,严重超时,然后上网看题解,发现是 ...