HDU 4111Alice and Bob(博弈+记忆化)

本文介绍了一种关于石子游戏的算法实现,游戏规则包括将石子合并或拿走单个石子,通过动态规划的方法确定游戏胜负。文章提供了一个具体的C++实现案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:有n堆石子,一次可以拿走一个石子,或者把一堆石子放在另一个石子上。不能再次操作的人输Alice先拿。问谁赢

思路:当石子个数大于1时,可以把他们放到一堆里+1次的操作数。石子数为1时,单独考虑。

设所有只有一个石子的是A堆,其他的石子可以合并的设为B堆。

每一次操作有:

1、把A堆 的两个石子合并。加入到B堆。

2、把B堆的石子减1

3、把A堆的一个石子加入的B堆

4、把A堆的石子减1

可以用记忆化来实现。。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
using namespace std;
int dp[59][50009];
int dfs(int z,int s)
{
    if(dp[z][s]!=-1) return dp[z][s];
    if(z==0) return dp[z][s] = s&1;
    if(z==1) return dp[1][s]=1;
    if(s==1) return dp[z][s] = dfs(z+1,0);
    dp[z][s] = 0;
    if(!dfs(z-1,s)) dp[z][s] = 1;///直接拿走1个的
    if(s>1&&!dfs(z,s-1)) dp[z][s] = 1;
    if(s>1&&!dfs(z-1,s+1)) dp[z][s] = 1;
    if(z>1&&!dfs(z-2,s?s+3:s+2)) dp[z][s] = 1;///合并之后加入s里
    return dp[z][s];
}
int main()
{
    freopen("in.txt","r",stdin);
    int cas,T=1,n;
    scanf("%d",&cas);
    memset(dp,-1,sizeof(dp));
    while(cas--)
    {
        scanf("%d",&n);
        int z=0,s=0,t=0;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&t);
            if(t==1) z++;
            else s+=t+1;
        }if(s>1) s--;
        printf("Case #%d: %s\n",T++,dfs(z,s)?"Alice":"Bob");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值