ZOJ 1827 The Game of 31

博弈的题目。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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值