]]>SPOJ 2154 Kruskalhttp://m.shnenglu.com/sdfond/archive/2010/02/06/107365.htmlsdfondsdfondSat, 06 Feb 2010 01:04:00 GMThttp://m.shnenglu.com/sdfond/archive/2010/02/06/107365.htmlhttp://m.shnenglu.com/sdfond/comments/107365.htmlhttp://m.shnenglu.com/sdfond/archive/2010/02/06/107365.html#Feedback0http://m.shnenglu.com/sdfond/comments/commentRss/107365.htmlhttp://m.shnenglu.com/sdfond/services/trackbacks/107365.html 猴子和Kruskal玩一个取矛_游戏Q给定n堆石子,n不大?00Q每堆石子的个数大于2于2 ^
32Q双方轮取子,每次可以从一堆中取最多k个,当一方取完石子后某堆矛_的个数是素数的话那么当前玩家莯。问猴子是否有必胜策略?br> 【题目分析?br> q是一道BT题,中间讄了许多trick。开始对题意没有完全理解Q错了很多次Q后来找来了数据Q才发现了问题?br> 题目中描q的莯{略是:"A
player wins if after his move the size of some heap is a prime
number."q句话乍一看以为是取完矛_后剩下的矛_个数是素数的时候就莯Q其实还隐藏着另一U可能:如果多堆矛_个数是素敎ͼ当前玩家无论怎样取都能获胜,因ؓ在他取完之后Q其他堆的石子个数是素数Q也满莯条g?br> 接下来考虑一般情c这个题目是限制中间状态的Nim游戏Q也是_对于一堆个Cؓn的石子而言Q它的SG值取决于于n的最大素数。注意这里题讑֏有了一个小trickQ题目说明了需要取1到k个,如果当前矛_个数本n是素敎ͼ当然是没用的Q因此是于n的最大素数。设于n的最大素数是p(题目中说明了矛_个数大于2Q因此p一定存?Q那么可以在k步以内到达p的一定是必胜态,而且是直接获胜,需要在输入的时候特?q一炚w要注意,在解决限制中间状态的Nim游戏时一般都需要特?。然后就是p
+ k + 1q个状态,因ؓ它可辄状态全是必胜态,因此它是必|态,SGgؓ0。现在考虑大于p + k + 1的状态,问题出来了。以p + k +
2q个状态ؓ例,因ؓ它可以到达p + 2 ... p + k + 1q些状态,因ؓp + 2 ... p +
k都是直接莯状态,如何判定他们的SG值呢Q如果假讑֮们的SG值是1Q那么p + k +
2q个状态的SG值应该是2。但是思考一下SG值的定义Q它是定义在一个DAG上的Q所有的状态最后都是可以在有限步内转移到终止?必|?。但是p + 1 ...
p + kq些状态都转移Cpq个状态上Q我们肯定不能认定p状态是l止态,因此仅仅凭借p + 1 ... p +
kq些状态是必胜态就单的把它们的SGD?是不恰当的;q些限制状态和以前的题目还不同Q这些限制状态都不能转移到终止态上Q但是由于题目的要求Q它们又都是必胜态,因此把它们的SGD为无I大更合适些?br> 仔细思考一下带限制状态的SG游戏Q可以发玎ͼ它们和一般的SG游戏的区别在于,在分析一般的SG游戏的时候,对于一个状态图而言Q{Udl止态的时候ƈ不意味着游戏l束Q因为玩家可以通过走其他的状态图来保证是否达到必胜态;但是带限制状态的SG游戏Q限制的状态双斚w是不敢走的,因ؓ一旦一方走入限制状态,另一方立刻获胜,游戏q止了。可以认为,只要走入限制态就相当于认输,对于双方玩家而言肯定都不会这样做Q因此这些限制状态就成了“ȝ?#8221;Q完全可以忽视这些状态(也就是说不存在到q些状态的转移Q。通过上述分析Q我们可以认定p
+ k +
2q个状态的SG值应该是1而不??br> 现在q个问题的做法就比较明朗了,对于每堆矛_Q去掉限制态的讨论后,变成了在集合{1...k}中选择元素的一个Subtraction
GameQ它的SG值是?k +
1)循环的?br> 然后是求最q素数的问题了,q个没有好办法,只能暴力枚D。对于一个数nQ在sqrt(n)到n之间存在素数Q感觉应该是Q但是不会证Q,因此最多枚举sqrt(n)ơ就能找到解。但是每ơ枚丑ֈ素的复杂度还是sqrt(n)Qd杂度q是比较高,我在本地跑数据跑?U,交上去超时了QSPOJ的时?0U,q居然也时Q数据够变态)。想了很久也没有什么新的算法,无奈只能在判素上下点功夫Q直接把Miller-Rabin搞出来了Q速度提高C2U,仍然时。后来又加了一些常C的优化,l于q了?br> 【ȝ?br> q个题目做了很长旉Q一斚w是审题不清,错了几次Q另一斚w是对于SG的理论理解的不够透彻Q想了很久终于想明白了;再有是优化法也花了很长时间。不q通过q个题目对于SG理论的理解又q了一步,感觉不错Q呵c?
]]>l合游戏ȝ——基本博弈问?/title>http://m.shnenglu.com/sdfond/archive/2010/02/06/107364.htmlsdfondsdfondSat, 06 Feb 2010 00:55:00 GMThttp://m.shnenglu.com/sdfond/archive/2010/02/06/107364.htmlhttp://m.shnenglu.com/sdfond/comments/107364.htmlhttp://m.shnenglu.com/sdfond/archive/2010/02/06/107364.html#Feedback0http://m.shnenglu.com/sdfond/comments/commentRss/107364.htmlhttp://m.shnenglu.com/sdfond/services/trackbacks/107364.html【概q?br> 最q的几次比赛Q博弈的题目一直不,而且博弈问题是一块比较复杂、庞大的内容Q因此在q里结一下,希望能够帮自q清一些思\Q争取也多来几个pdQ呵c?/p>
竞赛中出现的l合游戏问题一般都满以下特征Q?br> 1.
二h博弈游戏Q每个h都采用对自己最有利的策略,q且是两个h轮流做出决策 2.
在游戏中的Q意时刻,每个玩家可选择的状态是固定的,没有随机成分 3.
游戏在有限步数内l束Q没有^局出现 大部分的题目都满上q条Ӟ因此q里只讨论在上述条g范畴内的博弈问题。这cd弈问题,通常q有若干分类。一U是规定Ud最后一步的游戏者获胜,q种规则叫做Normal Play RuleQ另一U是规定Ud最后一步的游戏者输Q这U规则叫?span style="color: red;">Misere Play
RuleQ也UCؓAnti-SG游戏。此外,对于游戏的双方,如果二者博弈的规则相同Q那么称cL戏是对等(impartial games)的;否则UCؓ不^{游?/span>(partizan games
)。当初WHU的那场比赛就是由于对于这个概念不是很清晰Q导致看完题目之后就用SG定理来做Q浪费了很多机时。实际上Q解决不q等博弈问题的方法和普通的博弈问题QSG游戏Q是有区别的Q一般会采用动态规划或者surreal number?br> 【博弈基知识?br> 在SG游戏中,最Zh熟知的是必胜必|态,也叫NP态理论。注意的是,P态对应的是先手必败态,N态对应的是先手必胜态。必胜必败态理论是Q?br> 1. All terminal positions are
P-positions 2. From every
N-position, there is at least one move to a P-position 3. From every P-position, every move is to an
N-position 英文的表q非常简z清晎ͼ而且q个理论也很好理解,如果在当前状态的下一步可以走到必败态,那么当前玩家可以走到那个状态,把必败态推l另一方;如果所有可辄态都是必胜态,那么当前玩家无论如何赎ͼ都会把必胜态让l对斏V根据必胜必败态理论,我们可以递归的求出每个状态是N态还是P态。必胜必败态理论其实已l把博弈问题转化成了一个有向图Q借助图这个模型来分析问题Q得问题变得Ş象了许多。需要注意的是,q种SG游戏对应的有向图是无环的Q因为如果有环,那么游戏双方可能在环上不停的{换状态,游戏不能在有限步l止Q这样就不满组合游戏的特征3了?br> 然而在很多时候仅仅知道某个状态是必胜q是必|是不够的Q因为如果存在多个组合游戏(比如l典的NimQ,对应的状态集合非常大Q无法直接利用必胜必败态理论求解,因此需要用到博弈论中一个很重要的工PSG函数?br> 某个状态的SG函数值定义ؓ当前状态所有不可达的状态编号中最的~号Q其中终止态的SG函数值是0。有了这个工P引入一个非常强大的定理——SG分解定理Q?br> 多个l合游戏的SG函数值是每个l合游戏的函数值的和?/span>Q这里的和定义ؓ异或操作Q?br> SG分解定理的证明不是很难,其实和Nim的证明很像。根据这个定理,我们q道ؓ什么Nim的解法是异或所有的矛_个数了,因ؓ每堆矛_的SG值就是石子的个数。SG分解定理告诉我们MSG游戏都可以{化成Nim游戏来做?br> Nim中的一个变形就是拿走最后一块石子的人算输。通过修改SG的计规则,可以得出相同的结论(因ؓ当石子个数是1的时候SGgؓ0Q因此要单独处理Q;当然也可以利用一个叫做SJ定理的方法来做,依然是要处理当所有堆的SGg大于1的情c?br> 【博弈基本模型?br> 除了Nim模型Q很多模型都看似复杂Q最后都划归CNim模型上,然后利用SG分解来做的。在证明两种模型{h的时候,可以通过计算SG值判断是否相同,或者通过判断必胜{略的走法将其{化ؓNim。许多模型非常的奇Q其莯{略又千差万别,因此无法一一列DQ但是掌握一些经典模型是必须的,q样通过模型的{化可以简化问题的隑ֺ?br> l典模型1QNim变种?/span>包括Q?br> (1)
楼梯Nim。把奇数台阶的石子作为NimQ二者等P因ؓ必胜的策略是相同的?br> (2) 每次可以取k堆,q个是经典的Moore
Nim。它是泛化的Nim游戏?br> (3)
两堆矛_Q每ơ可以取一堆或两堆Q从两堆取得时候个数必ȝ同,谁先取完莯。这个是著名的威佐夫博弈Q跟黄金分割数有养I具体证明不是很清楚,但是用SG值打表可以找律。代码如下:
#include <cstdio> #include <algorithm> usingnamespace std; constint N =200010;
int x[N], y[N], z[N]; int main() { int n, a, b, c;
while (scanf("%d", &n) ==1&& n) { for (int i =0; i < n; i++) { scanf("%d %d %d", &a, &b, &c); x[i] = a - b; y[i] = b - c; z[i] = c - a; } sort(x, x + n); sort(y, y + n); sort(z, z + n); longlong ans =0; for (int i =0; i < n; i++) ans += (2* i +1- n) * (longlong)(x[i] + y[i] + z[i]); printf("%I64d\n", ans /2); }
#include <cstdio> #include <algorithm> usingnamespace std; constint N =10010;
int main() { int x[N], y[N], n;
while (scanf("%d", &n) ==1) { for (int i =0; i < n; i++) scanf("%d %d", &x[i], &y[i]); sort(x, x + n); sort(y, y + n); for (int i =0; i < n; i++) x[i] -= i; sort(x, x + n); int ans =0; for (int i =0; i < n /2; i++) ans += x[n-i-1] - x[i] + y[n-1-i] - y[i]; printf("%d\n", ans); }
]]>博弈论的一些题?/title>http://m.shnenglu.com/sdfond/archive/2009/05/31/86318.htmlsdfondsdfondSun, 31 May 2009 13:53:00 GMThttp://m.shnenglu.com/sdfond/archive/2009/05/31/86318.htmlhttp://m.shnenglu.com/sdfond/comments/86318.htmlhttp://m.shnenglu.com/sdfond/archive/2009/05/31/86318.html#Feedback0http://m.shnenglu.com/sdfond/comments/commentRss/86318.htmlhttp://m.shnenglu.com/sdfond/services/trackbacks/86318.htmlPOJ 2234 Matches Game HOJ 2533 Stone II POJ 2975 Nim HOJ 1367 A Stone Game POJ 2505 A multiplication game ZJU 3057 beans game POJ 1067 取石子游?br>POJ 2484 A Funny Game POJ 2425 A Chess Game POJ 2960 S-Nim POJ 1704 Georgia and Bob POJ 1740 A New Stone Game POJ 2068 Nim POJ 3480 John POJ 2348 Euclid's Game HOJ 2645 WNim POJ 3710 Christmas Game
POJ 3533 Light Switching Game