您的位置:首页 > 其它

ZOJ 1827 The Game of 31

2008-04-23 19:54 323 查看
博弈的题目。123456各四张花色,游戏开始时从中抽掉一些牌。每人一次抽取一张相加,和大于31者失败。求必胜策略。

设定状态表示为行动结束时剩下的sum。假如每种牌无限制张数,那么就等于抢七,必胜态为0、7、14、21、28。

但是当给定一些牌的时候,只能搜索。类似记忆化搜索,注意:牌数量不同,节点的状态也不同。

当抢到必胜态之后,上一个可以到达必胜态的节点一定是必败态。以无限制扑克战为例,比如( 13 12 11 10 9 8 ) ->7 都是必败态。假如你留给对方这样的状态,那么对手就赢了。

而必胜态只有两种情况:1.抢到0 2.下一个节点不可能是必胜态(对手无论如何都是必败,你就是必胜)。比如14 ->?无论如何都不可能达到必胜态。

当加入不同程度限制的时候,上述两法则依然成立。

试举一例:最后一样例,初始状态为7,留下扑克为12346.

12346显然是必败态。5为必胜态。7->5可以到达,即必败态,留下7给对手的人必输。

理论上所有博弈题目都是这两个步骤。程序很简单,但是理解起来挺费劲。我码了那么多字,却发现自己知道的比之前更少。


#include <cstdio>


#include <string>




char str[1000];


int card[7];




bool dfs ( int sum )




...{


int i;


for ( i = 1; i <= 6; i ++ )




...{


if ( card[i] && sum - i >= 0 )




...{


card[i] --;


if ( dfs ( sum - i ) )




...{


card[i] ++;


return false;


}


card[i] ++;


}


}


return true;


}




void proc ()




...{


int i, sum = 31;


for ( i = 0; i < 7; i ++ )


card[i] = 4;


int turn;


int len = strlen ( str );


for ( i = 0, turn = 0; i < len; i ++, turn = 1 - turn )




...{


sum -= str[i] - '0';


card[str[i] - '0'] --;


}


if ( sum > 0 )


if ( dfs ( sum ) )


turn = 1 - turn;


if ( sum == 0 )


turn = 1 - turn;


printf ( "%s %c ", str, 'A' + turn );


}




int main ()




...{


//freopen ( "in.txt", "r", stdin );


while ( scanf ( "%s", str ) != EOF )




...{


proc ();


}


return 0;


}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: