题目链接:hdu 2177

  这题不是普通的 Nim 博弈,我想它应该是另一种博弈吧,于是便推 sg 函数打了个 20*20 的表来看,为了方便看一些,我用颜色作了标记,打表代码如下:

 #include<cstdio>
#include<cstring>
#include<string>
#include<map>
#include<algorithm>
#include<windows.h>
using namespace std; int sg[][]; int dfs(int i, int j) {
if(i > j) swap(i,j);
if(sg[i][j] != - || sg[j][i] != -)
return sg[j][i] = sg[i][j]; bool *vis = new bool[];
for(int g = ; g < ; ++g)
vis[g] = ; for(int x = ; x <= i; ++x)
vis[dfs(i - x, j)] = vis[dfs(i - x, j - x)] = ;
for(int y = ; y <= j; ++y)
vis[dfs(i, j - y)] = ; for(int g = ; ; ++g) {
if(!vis[g]) {
delete[] vis;
return sg[j][i] = sg[i][j] = g;
}
}
} map<string, WORD> m;
inline void init() {
m["blue"] = | FOREGROUND_INTENSITY;
m["green"] = | FOREGROUND_INTENSITY;
m["cyan"] = | FOREGROUND_INTENSITY;
m["red"] = | FOREGROUND_INTENSITY;
m["pink"] = | FOREGROUND_INTENSITY;
m["yellow"] = | FOREGROUND_INTENSITY;
m["white"] = | FOREGROUND_INTENSITY;
} HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); inline void setColor(const string &color) {
SetConsoleTextAttribute(hConsole, m[color]);
} int main() {
int a,b;
memset(sg, -, sizeof sg);
sg[][] = ; init();
printf(" ");
setColor("yellow");
for(int i = ; i <= ; ++i)
printf("%2d ",i);
puts("");
for(int i = ; i <= ; ++i) {
setColor("yellow");
printf("%2d ",i);
for(int j = ; j <= ; ++j) {
if(dfs(i,j) == ) setColor("red");
else setColor("white");
printf("%2d ", dfs(i,j));
}
puts("");
} puts("");
setColor("cyan");
for(int i = ; i <= ; ++i)
for(int j = i; j <= ; ++j)
if(dfs(i,j) == ) printf("%d %d\n",i,j);
setColor("white"); return ;
}

  运行结果如下:

  看不出有什么规律,逐百度之,发现原来是威佐夫博奕,最后判定时需要用到黄金分割数什么的,不过是 O(1) 的复杂度,但杭电这道题还要输出第 1 步操作后的结果,也就是还要模拟一下,不知道它的数据量有多少,觉得直接暴力枚举应该会超时吧,便想写个二分,可是写了好久越写越乱,于是干脆试下暴力,竟然秒过了,后台数据估计少得可怜。需要输出的答案最多不会超过 3 组,但为了方便,我还是用 vector 来存下了符合要求的答案:

 #include<cstdio>
#include<cmath>
#include<set>
#include<vector>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int N = ;
const double p = (sqrt(5.0) + ) / ; bool ok(int a, int b) {
if(a > b) swap(a,b);
int k = b - a;
int c = int(k * p);
return c == a;
} int main() {
int a,b;
while(~scanf("%d %d",&a,&b),a) {
if(a > b) swap(a,b);
if(ok(a,b)) puts("");
else {
puts("");
for(int i = ; i < a; ++i)
if(ok(a - i, b - i)) printf("%d %d\n", a - i, b - i);
vector<pair<int,int> > v;
for(int i = ; i < a; ++i)
if(ok(a - i, b)) v.push_back(make_pair(a - i, b));
for(int i = ; i < b; ++i)
if(ok(a, b - i)) {
if(a > b - i) v.push_back(make_pair(b - i, a));
else v.push_back(make_pair(a, b - i));
}
sort(v.begin(), v.end());
int m = unique(v.begin(), v.end()) - v.begin();
for(int i = ; i < m; ++i)
printf("%d %d\n", v[i].first, v[i].second);
}
}
return ;
}

hdu 2177 取(2堆)石子游戏(威佐夫博奕)的更多相关文章

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

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

  2. HDU 2177 取(2堆)石子游戏

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

  3. HDU 2177 取(2堆)石子游戏 (威佐夫博弈)

    题目思路:威佐夫博弈: 当当前局面[a,b]为奇异局时直接输出0 否则: 1.若a==b,输出(0 0): 2.将a,b不停减一,看能否得到奇异局,若有则输出: 3.由于 ak=q*k(q为黄金分割数 ...

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

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

  5. poj 1067 取石子游戏( 威佐夫博奕)

    题目:http://poj.org/problem?id=1067 题意:有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的 ...

  6. hdu 2177 取(2堆)石子游戏 博弈论

    由于要输出方案,变得复杂了.数据不是很大,首先打表,所有whthoff 的奇异局势. 然后直接判断是否为必胜局面. 如果必胜,首先判断能否直接同时相减得到.这里不需要遍历或者二分查找.由于两者同时减去 ...

  7. HDU 2176 取(m堆)石子游戏(Nim)

    取(m堆)石子游戏 题意: Problem Description m堆石子,两人轮流取.只能在1堆中取.取完者胜.先取者负输出No.先取者胜输出Yes,然后输出怎样取子.例如5堆 5,7,8,9,1 ...

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

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

  9. HDU 2176 取(m堆)石子游戏 (尼姆博奕)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2176 m堆石子,两人轮流取.只能在1堆中取.取完者胜.先取者负输出No.先取者胜输出Yes,然后输出怎 ...

随机推荐

  1. Java 操作符

    子系统的特点 instanceof 操作符 Animal类是Dog的直接父类,Creature类和Object类是Dog的间接父类,因此 Dog dog=new Dog(); System.out.p ...

  2. CDN缓存那些事

    CDN是什么? 谈到CDN的作用,可以用8年买火车票的经历来形象比喻: 8年前,还没有火车票代售点一说,12306.cn更是无从说起.那时候火车票还只能在火车站的售票大厅购买,而我所住的小县城并不通火 ...

  3. struts2:数据校验,通过Action中的validate()方法实现校验,图解

    根据输入校验的处理场所的不同,可以将输入校验分为客户端校验和服务器端校验两种.服务器端验证目前有两种方式: 第一种 Struts2中提供了一个com.opensymphony.xwork2.Valid ...

  4. LeetCode Power of Three

    原题链接在这里:https://leetcode.com/problems/power-of-three/ 与Power of Two类似.检查能否被3整除,然后整除,再重复检查结果. Time Co ...

  5. linux的mount(挂载)命令

    前言: 1.挂载点必须是一个目录. 2.一个分区挂载在一个已存在的目录上,这个目录可以不为空,但挂载后这个目录下以前的内容将不可用. 对于其他操作系统建立的文件系统的挂载也是这样.但是需要理解的是:光 ...

  6. js的实参是按值传递还是按引用传递

    1.如果是基本类型,则是按值传递 var str = 'one';function f(string) {    string = 'two';}f(str);console.log(str); // ...

  7. kafka java代码实现消费者

    public class KafkaConsumer { public static void main(String[] args) { Properties props = new Propert ...

  8. 自动生成pdf书签(仅适用于Adobe Acrobat on windows )

    必备软件 1.Adobe Acrobat. 2.AutoBookmark 为adobe acrobat的自动生成书签的插件(我用的这个:AutoBookmark Standard Plug-in),下 ...

  9. Postgres Plus Advanced Server installation

    # setenforce Permissive # ./ppasmeta-9.3.1.3-linux-x64.run --mode text Installation Directory [/opt/ ...

  10. C# TreeView的CheckBox 父/子节点点击联动选择效果

    注: 点击时请正常速度点击,不然会出现“奇怪”现象!!! /// <summary> /// 节点点击 子级->同级->父级 /// </summary> /// ...