【题目】

Description

The funny stone game is coming. There are n piles of stones, numbered with 0, 1, 2, ..., n − 1. Two
persons pick stones in turn. In every turn, each person selects three piles of stones numbered i, j, k
(i < j, j ≤ k and at least one stone left in pile i). Then, the person gets one stone out of pile i, and
put one stone into pile j and pile k respectively. (Note: if j = k, it will be the same as putting two
stones into pile j). One will fail if he can’t pick stones according to the rule.
David is the player who first picks stones and he hopes to win the game. Can you write a program
to help him?
The number of piles, n, does not exceed 23. The number of stones in each pile does not exceed 1000.
Suppose the opponent player is very smart and he will follow the optimized strategy to pick stones.

Input
Input contains several cases. Each case has two lines. The first line contains a positive integer n
(1 ≤ n ≤ 23) indicating the number of piles of stones. The second line contains n non-negative integers
separated by blanks, S0, . . . , Sn−1 (0 ≤ Si ≤ 1000), indicating the number of stones in pile 0 to pile
n − 1 respectively.
The last case is followed by a line containing a zero.
Output
For each case, output a line in the format ‘Game t: i j k’. t is the case number. i, j and k indicates
which three piles David shall select at the first step if he wants to win. If there are multiple groups of
i, j and k, output the group with the minimized lexicographic order. If there are no strategies to win
the game, i, j and k are equal to ‘-1’.

Sample Input
4
1 0 1 100
3
1 0 5
2
2 1
0
Sample Output
Game 1: 0 2 3
Game 2: 0 1 1
Game 3: -1 -1 -1

【题目翻译】

  David 玩一个石子游戏。游戏中,有n堆石子,被编号为0..n-1。两名玩家轮流取石子。每一轮游戏,每名玩家选取3堆石子i,j,k(i<j,j<=k,且至少有一枚石子在第i堆石子中),从i中取出一枚石子,并向j,k中各放入一枚石子(如果j=k则向k中放入2颗石子)。最先不能取石子的人输。

请编程帮助David。

石子堆的个数不会超过23,每一堆石子不超过1000个。

【分析】

  首先,假设第i堆有xi个石子,那么可以先把xi%2。

  因为在同一堆中的两颗石子是一模一样的。对方对这颗石子做什么,你就可以对另外一颗石子做同样的事,相当于这两颗一样的石子不存在。

  因为每颗石子可以变成两颗放到后面去,也就是说它的转移状态和它的编号有关。

  可以将每一颗石子看作是一堆石子,如果它是第p堆中的石子,把么它所代表的这堆石子的个数为n-1-p。

  因为石子堆是互不干扰的,因此这个游戏可以看作由若干个只有一堆石子的游戏组成。(把其单独考虑开来)

  求它能到达的子状态的尼姆和更新自己的sg值即可。跟扫楼梯一题差不多,即使这堆石子的个数为偶数个,他可能还是有用的,即可以拆分也把状态改变为平衡状态的,要把这个也考虑上。(好像说得不是很清楚,具体看代码吧~~)

代码如下:(看错数据范围了,懒得改了,就酱吧~)

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define Maxn 1010 int n;
int a[*Maxn],b[*Maxn],sg[*Maxn];
bool vis[*Maxn]; void get_sg(int x)
{
memset(vis,,sizeof(vis));
for(int i=;i<x;i++)
for(int j=i;j<x;j++)
{
vis[sg[i]^sg[j]]=;
}
for(int i=;i<=;i++)
if(vis[i]==) {sg[x]=i;break;}
} bool output(int x,int now)
{
for(int i=x-;i>=;i--)
for(int j=i;j>=;j--)
if((sg[i]^sg[j])==now)
{
printf("%d %d %d\n",n-x,n-i,n-j);
return ;
}
return ;
} int main()
{
int kase=;
for(int i=;i<=;i++) get_sg(i);
while()
{
scanf("%d",&n);
if(n==) break;
int ans=;
for(int i=;i<=n;i++) scanf("%d",&a[i]);
for(int i=;i<=n;i++) b[i]=a[n-i+];
for(int i=;i<=n;i++)
{
if(b[i]%==) ans^=sg[i];
}
printf("Game %d: ",++kase);
if(ans==) {printf("-1 -1 -1\n");continue;}
int mx=;
for(int i=;(<<i)<=ans;i++)
if((<<i)&ans) mx=(<<i);
for(int i=n;i>=;i--)
if(b[i]!=) {if(output(i,ans^sg[i])) break;}
}
return ;
}

[UVA1378]

2016-04-17 17:12:38

【UVA1378】A Funny Stone Game (博弈-求SG值-输出方案)的更多相关文章

  1. hdu 1536 S-Nim_求sg值模版

    题意:给你很n堆石头,k代表你有k种拿法,然后给出没堆石头的数量,求胜负 直接套用模版 找了好久之前写的代码贴上来 #include<iostream> #include<algor ...

  2. HDU 1729 类NIM 求SG

    每次有n个盒子,每个盒子有容量上限,每次操作可以放入石头,数量为不超过当前盒子中数量的平方,不能操作者输. 一个盒子算一个子游戏. 对于一个盒子其容量为s,当前石子数为x,那么如果有a满足 $a \t ...

  3. 题解报告:hdu 1847 Good Luck in CET-4 Everybody!(入门SG值)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1847 Problem Description 大学英语四级考试就要来临了,你是不是在紧张的复习?也许紧 ...

  4. UVA1378 A Funny Stone Game —— SG博弈

    题目链接:https://vjudge.net/problem/UVA-1378 题意: 两个人玩游戏,有n堆石子,两人轮流操作:于第i堆石子中取走一块石子,然后再往第j.k堆中各添加一块石子.其中 ...

  5. 博弈之——SG模板

    很久没搞博弈了.先来写个模板: 现在我们来研究一个看上去似乎更为一般的游戏:给定一个有向无环图和一个起始顶点上的一枚棋子,两名选手交替的将这枚棋子沿有向边进行移动,无法移动者判负.事实上,这个游戏可以 ...

  6. 简单易懂的博弈论讲解(巴什博弈、尼姆博弈、威佐夫博弈、斐波那契博弈、SG定理)

    博弈论入门: 巴什博弈: 两个顶尖聪明的人在玩游戏,有一堆$n$个石子,每次每个人能取$[1,m]$个石子,不能拿的人输,请问先手与后手谁必败? 我们分类讨论一下这个问题: 当$n\le m$时,这时 ...

  7. Gym 101246D Fire in the Country(dfs求SG函数)

    http://codeforces.com/gym/101246/problem/D 题意: 给定一个无向有环图,大火从1点开始,每个时间点与它相邻的点也将会着火,现在有两个人轮流操作机器人,机器人从 ...

  8. 学习笔记--博弈组合-SG函数

    fye学姐的测试唯一的水题.... SG函数是一种游戏图每个节点的评估函数 具体定义为: mex(minimal excludant)是定义在整数集合上的操作.它的自变量是任意整数集合,函数值是不属于 ...

  9. 博弈的SG函数理解及模板

    首先定义mex(minimal excludant)运算,这是施加于一个集合的运算,表示最小的不属于这个集合的非负整数.例如mex{0,1,2,4}=3.mex{2,3,5}=0.mex{}=0. 对 ...

随机推荐

  1. WPF组件开发

    在做组件之前,为了适应框架,我们需要有一个基类,并将这个基类打包成一个模板,让大部分组件去使用这个模板. 组件的基类就不多讲了,上篇文章中已经说过了.这是地址: http://www.cnblogs. ...

  2. oracle合并查询

    1). Union 该操作符用于取得两个结果集的并集.当使用该操作符时,会自动去掉结果集中重复行. 2).union all 该操作符与union相似,但是它不会取消重复行,而且不会排序. 3). I ...

  3. android中的样式和主题

    有的时候我们一个页面要用很多个textview,而且这些textview的样式非常相像,这种情况下我们可以把这些样式抽取出来,然后在每个textview中引用即可,这样修改起来也方便. 我们来看一个简 ...

  4. Java基础知识强化之网络编程笔记01:InetAddress类的概述和使用

    1. InetAddress类 InetAddress是Java对IP地址的封装,在java.net中有许多类都使用到了InetAddress,包括ServerSocket,Socket,Datagr ...

  5. Go语言学习资料汇总

    网站: Go语言官网(访问)(中文镜像) Go语言中文网(访问) Go编译器(访问) Go语言中国社区(访问) golanghome(访问) GoLang中国(访问) Gopher Academic( ...

  6. 各种SQL类型

    一.SQL:通常我们说的sql指的是最古老运用最方法的结构化查询语言(Structured Query Language),大部分人接触最多的是数据库查询使用,关系型数据库基本都支持. 二.T-SQL ...

  7. [DEncrypt] Encrypt--加密/解密/MD5加密 (转载)

    点击下载  Encrypt.zip 这个类是关于加密,解密的操作,文件的一些高级操作1.Encrypt加密2.Encrypt解密3.Encrypt MD5加密看下面代码吧 /// <summar ...

  8. Angularjs总结(三)摸态框的使用

    静态页面: <input class="btn btnStyle " value="提 取" type="button" ng-cli ...

  9. 数据库学习(整理)----6--Oracle如何快速备份和多次备份数表数据

    1.说明:  这里假设一种应用场景! 假设,银行系统中有大量的数据需要及时备份,如何才能快速高效呢! 条件需求: (1).不能设置同步锁(设置的会影响银行正常业务进行!使得银行系统处于维护状态,这是不 ...

  10. 用3种方法在 operator= 中处理“自我赋值”

    假设你建立一个class 用来保存一个指针指向一块动态分配的位图. class Bitmap {......}; class Widget{ ... private: Bitmap* pb ; }; ...