HDOJ 5754 (2016多校联合训练 Training Contest 3) Life Winner Bo
2016-07-28 10:58
190 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5754
一道博弈大汇总,一道题当做四道题来做=.=,题意是给我们四种棋子,每种棋子的走法不同,问我们谁会赢。
1.王:
王的行走方式是只能向下或者向右或者向右下移动一格。
王我们可以直接分析必胜点和必败点,首先我们的终点就是必胜点,而必胜点的左上三个格子都是必败点,我们这样推就会发现必胜点(O)和必败点(X)会按一下方式排列。
OXOXOXOXOXOXOXOXOXOXO
XXXXXXXXXXXXXXXXXXXXXXXX
OXOXOXOXOXOXOXOXOXOXO
XXXXXXXXXXXXXXXXXXXXXXXX
OXOXOXOXOXOXOXOXOXOXO
也就是说只要行和列都是奇数,那么先手就会输,其他情况都是先手赢。
2.车:
车的行走方式是能向下或者向移动任意格子。
这个问题其实我们可以转换成取石子的方式,有n,m个石子的两堆石子,我们可以一次任意从两堆中的一堆中取任意个石子,问我们谁能够取到最后一个。
关于这个问题我们很容易找到一个平衡点,那就是当两堆的个数相等的时候,当两堆个数相等的时候很明显下一个人只能够破坏这个平衡,而下一个人又可以恢复这个平衡,所以两堆相等就是必胜点,也就是说如果一开始n,m相等,那么先手就输了,不等则先手赢。
3.马:
马的行走方式是走日字,只能向右下的方向移动。
首先马和车一样,存在这个平衡点,那就是n和m相等的时候,但是n,m相等并不代表就一定能够移动到终点,必须得存在(n-1)%3==0才行,如果一开始就在这个平衡点上那么先手就输了,如果第一步就能够移动到这个平衡点上,那么先手就赢了,其他的情况都应该是没有结果。
4.王后:
我相信大多数的选手卡在这题的话,都是卡在这个王后上,王后的移动方式是可以向下或者向右或者向右下移动任意格子,那么换成是取石子的话就是有n,m个石子的两堆石子,我们可以一次任意从两堆中的一堆中取任意个石子或者两堆同时取任意个旗子,问我们谁能够取到最后一个。
这个是威佐夫博弈,相信很多没有听过这个威佐夫博弈的同学比赛的时候都想通过打表俩解决,首先,打表肯定是对的,但是小编觉得,打表真的很难保证表的正确性,相信很度同学度觉得自己明明表是打的对的,为什么就是WA,肯定什么地方多多少少还是有问题的,那么小编这里就直接用威佐夫博弈的公式来求解。
#include <cmath>
#include <cstdio>
#include <iostream>
typedef long long ll;
using namespace std;
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int type, n, m;
scanf("%d%d%d", &type, &n, &m);
if(type == 1)
{
if(n%2!=0 && m%2!=0) printf("G\n");
else printf("B\n");
}
if(type == 2)
{
if(n == m) printf("G\n");
else printf("B\n");
}
if(type == 3)
{
if((n==m&&(n-1)%3==0)) printf("G\n");
else if((n==2&&m==3) || (n==3&&m==2)) printf("B\n");
else if((n-1==m-2)&&(n-2)%3==0 || (n-2==m-1)&&(n-3)%3==0) printf("B\n");
else printf("D\n");
}
if(type==4)
{
n--,m--;
if(n<m)swap(n,m);
int k=n-m;
n=(int)(k*(1+sqrt(5))/2.0);
if(n==m) printf("G\n");
else printf("B\n");
}
}
return 0;
}
一道博弈大汇总,一道题当做四道题来做=.=,题意是给我们四种棋子,每种棋子的走法不同,问我们谁会赢。
1.王:
王的行走方式是只能向下或者向右或者向右下移动一格。
王我们可以直接分析必胜点和必败点,首先我们的终点就是必胜点,而必胜点的左上三个格子都是必败点,我们这样推就会发现必胜点(O)和必败点(X)会按一下方式排列。
OXOXOXOXOXOXOXOXOXOXO
XXXXXXXXXXXXXXXXXXXXXXXX
OXOXOXOXOXOXOXOXOXOXO
XXXXXXXXXXXXXXXXXXXXXXXX
OXOXOXOXOXOXOXOXOXOXO
也就是说只要行和列都是奇数,那么先手就会输,其他情况都是先手赢。
2.车:
车的行走方式是能向下或者向移动任意格子。
这个问题其实我们可以转换成取石子的方式,有n,m个石子的两堆石子,我们可以一次任意从两堆中的一堆中取任意个石子,问我们谁能够取到最后一个。
关于这个问题我们很容易找到一个平衡点,那就是当两堆的个数相等的时候,当两堆个数相等的时候很明显下一个人只能够破坏这个平衡,而下一个人又可以恢复这个平衡,所以两堆相等就是必胜点,也就是说如果一开始n,m相等,那么先手就输了,不等则先手赢。
3.马:
马的行走方式是走日字,只能向右下的方向移动。
首先马和车一样,存在这个平衡点,那就是n和m相等的时候,但是n,m相等并不代表就一定能够移动到终点,必须得存在(n-1)%3==0才行,如果一开始就在这个平衡点上那么先手就输了,如果第一步就能够移动到这个平衡点上,那么先手就赢了,其他的情况都应该是没有结果。
4.王后:
我相信大多数的选手卡在这题的话,都是卡在这个王后上,王后的移动方式是可以向下或者向右或者向右下移动任意格子,那么换成是取石子的话就是有n,m个石子的两堆石子,我们可以一次任意从两堆中的一堆中取任意个石子或者两堆同时取任意个旗子,问我们谁能够取到最后一个。
这个是威佐夫博弈,相信很多没有听过这个威佐夫博弈的同学比赛的时候都想通过打表俩解决,首先,打表肯定是对的,但是小编觉得,打表真的很难保证表的正确性,相信很度同学度觉得自己明明表是打的对的,为什么就是WA,肯定什么地方多多少少还是有问题的,那么小编这里就直接用威佐夫博弈的公式来求解。
#include <cmath>
#include <cstdio>
#include <iostream>
typedef long long ll;
using namespace std;
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int type, n, m;
scanf("%d%d%d", &type, &n, &m);
if(type == 1)
{
if(n%2!=0 && m%2!=0) printf("G\n");
else printf("B\n");
}
if(type == 2)
{
if(n == m) printf("G\n");
else printf("B\n");
}
if(type == 3)
{
if((n==m&&(n-1)%3==0)) printf("G\n");
else if((n==2&&m==3) || (n==3&&m==2)) printf("B\n");
else if((n-1==m-2)&&(n-2)%3==0 || (n-2==m-1)&&(n-3)%3==0) printf("B\n");
else printf("D\n");
}
if(type==4)
{
n--,m--;
if(n<m)swap(n,m);
int k=n-m;
n=(int)(k*(1+sqrt(5))/2.0);
if(n==m) printf("G\n");
else printf("B\n");
}
}
return 0;
}
相关文章推荐
- [leetcode]373. Find K Pairs with Smallest Sums -- JavaScript代码
- js实现的增删改查操作
- AngularJS Directive 隔离Scope数据交互
- JavaScript学习一
- 转:前端规范(整理的过程就是学习的过程,学习的过程就是总结的过程)
- cJSON 解析器开源项目学习笔记
- bootstrap-treeview
- jsp base标签与meta标签学习小结
- Jquery blokckUI 快速入门
- js部分代码执行机制
- 使用jQuery.form插件,实现完美的表单异步提交
- gulp + webpack + sass 学习
- JS中正则表达式只有3种匹配模式(没有单行模式)详解
- 33个优秀的HTML5应用演示 (转)
- 33个优秀的HTML5应用演示 (转)
- Javascript模块化编程(三):require.js的用法
- Javascript模块化编程(二):AMD规范
- Javascript模块化编程(一):模块的写法
- AngularJS中的API(接口)简单实现
- 关于bootstrap弹出二级对话框的使用