题目大意:有一个无限长的一维的棋盘,棋盘上N个格子放置着棋子。两个人轮流操作,每次操作能选择其中一个棋子向左移动,但不能越过其它棋子或者两枚棋子放在同一格中,最后不能操作的人算输,问先手是否必胜?

思路:就是裸的阶梯博弈(staircase nim)方法也很简单。首先每个棋子能向右移动的距离是有限的,最多到前一个棋子处就停止了,比如第一个sample :1 2 3 每个棋子都不能移动就是 0 0 0 第二个sample: 1 5 6 7 9 12 14 17 就是0 3 0 0 1 2 1 2 这样每次移动一枚棋子向左n步,相当于把对应第二排的那个数据减去n,那个数据右边一个数加上n
这样问题就转变成了:有n堆石头,每次可以从一堆中拿出一些或全部石头给相邻的右边的一堆石头,或者最后一堆减去一些或全部石头,谁不能操作谁输,问先手是否必胜?
关于这个问题的结论和证明网上多如牛毛,结论是:假设从最后一堆石头开始与上一堆相间的石头数的异或和为P,P为0时先手必败反之必胜。比如a1,a2,a3,a4,a5   P的值就是a5 xor a3  xor a1

证明无非就是说明当不为平衡态时必然存在操作使局面进入平衡态,而局面已然是平衡态时任何操作都会破坏平衡。这里不再累述。说一下对这个问题的一些直观认识:为了叙述方便,可以把与最后一堆石头相间的石头称为有用堆(这里是我生造的一个词)而其它堆称为无用

堆。

□■□■□■□■□■□

如图空心方块表示有用堆,实心方块表示无用堆,显然把无用堆的石头放到有用堆的操作都是没有意义的,因为这次从无用堆放进多少块石头到有用堆,下一次操作就能将这些运进来的石头扔给下一个无用堆或者扔掉(最后一堆石头),而有用堆石头的序列分毫未变,因此只需看有用堆的石头情况即可。而有用堆的石头放进无用堆相当于扔掉的操作,因为刚才已经证明无用堆中的石头是不起作用毫无意义的,这样就将问题化为了有用堆的NIM游戏!!因此只需计算有用堆的异或和就能计算出先手的胜负情况

//poj1704

#include<cstdio>

#include<string.h>

#include<iostream>

using namespace std;

int a[1009]={0};

void qsort(int l,int r)

{

int i=l,j=r,mid=a[(l+r)>>1],temp;

while(i<j)

{

while(a[i]<mid)i++;while(a[j]>mid)j--;

if(i<=j)

{

temp=a[i];a[i]=a[j];a[j]=temp;

i++;j--;

}

}

if(i<r)qsort(i,r);

if(l<j)qsort(l,j);

}

int main()

{

int n,t,chess[1009]={0};

scanf("%d",&t);

while(t--)

{

int x=0,last=0;

scanf("%d",&n);

for(int i=1;i<=n;i++)scanf("%d",&a[i]);

qsort(1,n);

for(int i=1;i<=n;i++)

{

chess[i]=a[i]-last-1;

last=a[i];

}

for(int i=n;i>=1;i=i-2)

x=x^chess[i];

if (x!=0)printf("Georgia will win\n");else printf("Bobwill win\n");

}

return 0;

}

调试小结:3次WA 原因:未看清棋子顺序不是从小到大!!

最新文章

  1. 说说设计模式~桥梁模式(Bridge)
  2. 开始对函数式编程 产生了尊崇感,因为Spring4.x ,Grooxy,Lisp,网易出来伞哥和他的博客
  3. 深入理解Redis:底层数据结构
  4. 如何在Dynamics CRM 2011 的窗体表单上加载报表
  5. 删除字符串第一个byte
  6. Ubuntu 下一个可用的音乐播放器
  7. pinyin4j使用示例
  8. Windows Phone 8 开发初体验
  9. maven jetty plugin
  10. 怎样解决Ubuntu发热严重地问题
  11. 查询Python版本
  12. Unity与安卓IOS交互
  13. HDU 5988 Coding Contest(浮点数费用流)
  14. [Algorithm] Binary tree: Level Order Traversal
  15. Linux命令之lsb_release - 查看当前系统的发行版信息
  16. ASK,OOK,FSK的联系和区别
  17. java-spark的各种常用算子的写法
  18. Java—进程与线程
  19. PAT 天梯赛 L1-010. 比较大小 【水】
  20. 一些C语言里面的编程

热门文章

  1. P2956 [USACO09OCT]机器人犁田The Robot Plow
  2. 事件对象(示例、封装函数EventUtil())
  3. 开发原生安卓cordova插件(有原生界面)
  4. 读取Chrome书签文件
  5. FPGA编程技巧系列之按键边沿检测
  6. css-test
  7. Chrome开发者工具关于网络请求的一个隐藏技能
  8. C++#pragma pack指令
  9. SQLite -创建表
  10. VINS-Fusion代码阅读(四)