HDU4111-2011成都

本文讨论了石子游戏中的策略选择,通过将问题转换为熟悉的游戏形式,分析了如何利用记忆化搜索来解决此类问题。文章详细介绍了记忆化搜索的实现过程,并提供了求解方法。

题目: 题目链接

 

题目意思:

题目转换为熟悉的石子游戏就是,这里有m堆石子,每次可以把任意两堆合并,或者从某一堆中拿走一个,是不能操作

谁就输了。

 

由于总数不变,最终总是要一个个拿完。那么有机会获胜的一方,肯定是先要把所有的合在一起,那么最终就拼奇偶数

了。所以双方都要合并。

而且如果没有某堆只有一个的话,对方是阻挡不住的,没有取完,便被合并了。

所以就要考虑某堆只有一个的情况,单独考虑。

其中的操作包括:

1:把某堆只有一个的,取走

2:把两堆只有一个的,合并

3:把某堆只有一个的,合并给不是一个的

4:把不是一个的,取走一个

记忆化搜索

 

#include <iostream>
#include <cstdio>
#include <string>
#include <string.h>
#include <map>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <queue>
#include <set>
#include <stack>
#include <functional>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <numeric>
#include <cassert>
#include <bitset>
#include <stack>
#include <ctime>
#include <list>
#define INF 0x7fffffff
#define max3(a,b,c) (max(a,b)>c?max(a,b):c)
#define min3(a,b,c) (min(a,b)<c?min(a,b):c)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
int t, n, index, sum, one;
int sg[55][60005];
int getsg(int i, int j)
{
    if(sg[i][j] != -1)
    return sg[i][j];
    if(j == 1)
    return sg[i][j] = getsg(i+1, 0);
    sg[i][j] = 0;
    //去掉一个的
    if(i >= 1 && !getsg(i-1, j))
    sg[i][j] = 1;
    //去掉大于1的中的一个
    else if(j >= 1 && !getsg(i, j-1))
    sg[i][j] = 1;
    //把1合并到非1
    else if(i >= 1 && j>0 && !getsg(i-1, j+1))
    sg[i][j] = 1;
    //双1合并
    else if(i >= 2 && ((j==0 && !getsg(i-2, j+2))|| (j && !getsg(i-2, j + 3))))
    sg[i][j] = 1;
    return sg[i][j];
}
int main()
{
    scanf("%d", &t);
    int cnt = 0;
    mem(sg, -1);
    while(t--)
    {
        cnt++;
        scanf("%d", &n);
        sum = 0;
        one = 0;
        for(int i = 0; i < n; ++i)
        {
            scanf("%d", &index);
            if(index == 1)
            one ++;
            else
            sum += (index + 1);
        }
        if(sum)
        sum--;
        printf("Case #%d: ", cnt);
        if(getsg(one, sum))
        printf("Alice\n");
        else
        printf("Bob\n");
    }
    return 0;
}


 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值