博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
hdu 1729 sg博弈
阅读量:5124 次
发布时间:2019-06-13

本文共 2143 字,大约阅读时间需要 7 分钟。

做过的第一题真正意思上的sg博弈。然后各种不会。

转载出处:

博弈SG函数问题、寻找必败态
题目大意:(取石子游戏)有n个箱子,体积为Si,当前箱子里的石子数为Ci。两个人轮流往箱子里放石子,而且每一次放是数量都有限制,不能超过当前箱子内石子数的平方。例如箱子里有3颗石子,那么下一个人就可以放1~9颗石子,直到箱子被装满。当有一方放不下石子时游戏结束,最后放不下石子的人输。
算法分析:

PSSG(X)=mex(SG(X->Y1),SG(X->Y2),SG(X->Y3),...........,SG(X->YN));是y1 ,y2 ,y3......的SG值取mex;而不是对(Y1Y2,...YN)取mex;

这个文章很不错。

那么对于这题对于每一堆,放石子放满就想当于满的时候取s-c个,反向只是让我理解题意更深。

首先我们知道(S,S)这个局面是必败局面。

对于每一堆能加的数量有限,而当c的值(大于或者等于)D=sqrt(s) 或者 D=sqri(s)+1的时候就可以一次完成,就是说可以从当前局面到达(S,S)的局面,所以当前局面是必胜局面。

而这种情况下,你能造成的局面有集合A={0,1,2,...,s-c-1};因为你可以去s-c,s-c-1,s-c-2,.....,1;那么对应mex(x)函数(即A中未出现的最小的一个数字),那么自然该局面的SG值就是s-c了;

另外当c的值小于D的时候,是不可能一下子加满的,因为c*c+c绝对是小于s的;那么小于D的局面一定能够是必输的吗?很显然不是的。

对于(S,D-1)这个局面,一定是必输,因为他能到的局面都是必胜!现在c小于D,那么如果(S,C)这个局面能到(S,D);就代表这个局面是必胜的。所以现在SG值要在新集合(D,C)中求,而求法与上面的相同求新的D,所以可以用递归函数:当C>D时,返回(S-C)

差不多就是这样。

其实D = sqrt(s);这里算是个加速,要不然就要:while(d*d+d < S) d++;这样会很慢的。

 

思路:这题明显的sg函数。可惜我纠结了半天没想起思路来。设当前的箱子容量为si,求出一个t满足:+ t * t < si,若是当前箱子里有ci颗石头,

         1ci > t 则必胜;

         2ci == t 则必败;

         3ci < t不可立即断定,将t作为si递归调用函数。

当满足ci > t时,return si - ci 作为当前状况的sg值。因为:

如图:

HDU 1729 Stone Game - _眼淚笑了 - _眼淚笑了

cisi点时,为有向图的端点,出度为0,也就是必败点,所以sg值为0

ci 位于si - 1时,ci的端点可能的sg值构成的凑集为{

0},所以当前sg 1

ci 位于si - 2 时,ci的端点可能的sg值构成的凑集为{

0 1},所以当前的sg值为2

可得,ci地点地位的sg值为si - ci

 

View Code
// I'm lanjiangzhou//C#include 
#include
#include
#include
#include
#include
//C++#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;//*************************OUTPUT*************************#ifdef WIN32#define INT64 "%I64d"#define UINT64 "%I64u"#else#define INT64 "%lld"#define UINT64 "%llu"#endif//**************************CONSTANT***********************#define INF 0x3f3f3f3f// aply for the memory of the stack//#pragma comment (linker, "/STACK:1024000000,1024000000")//endconst int maxn = 1000000+100;int sg[maxn];int mex(int s,int c){ int t=(int)sqrt((double)s); while(t+t*t>=s) t--; //找到符合条件的点 if(t

 

转载于:https://www.cnblogs.com/lanjiangzhou/archive/2013/04/14/3020467.html

你可能感兴趣的文章
C# ADO.NET
查看>>
快速排序算法
查看>>
HDU 1394 Minimum Inversion Number
查看>>
JQuery方法
查看>>
P1049 装箱问题
查看>>
第一百二十六节,JavaScript,XPath操作xml节点
查看>>
LightOJ 1393 Crazy Calendar(博弈)题解
查看>>
第一步:Axure 使用svn多人协作产品开发(提交文件)
查看>>
用IIS配置反向代理
查看>>
sufeinet
查看>>
论算法的实际应用——泡妞论
查看>>
HTTP 错误 404.3 – Not Found 由于扩展配置问题而无法提供您请求的页面。如果该页面是脚本,请添加处理程序。如果应下载文件,请添加 MIME 映射。...
查看>>
js和layerjs配合实现的拖拽表格列
查看>>
Spring MVC集成slf4j-logback
查看>>
java常量池
查看>>
URL类
查看>>
flask(精讲)
查看>>
Java异常处理原则与技巧总结
查看>>
springboot快速入门
查看>>
wget 命令用法详解
查看>>