• #SG函数,记忆化搜索#HDU 4111 Alice and Bob


    题目

    Alice和Bob两个好朋友又开始玩取石子了。

    游戏开始时,有(n)堆石子排成一排,然后他们轮流操作(Alice先手),每次操作时从下面的规则中任选一个:

    ·从某堆石子中取走一个

    ·合并任意两堆石子

    不能操作的人输。Alice想知道,她是否能有必胜策略。


    分析

    如果不存在大小为1的石堆,则操作次数一定被控制为(sum+n-1),判断奇偶性即可,
    若存在大小为1的石堆,它有五种后继状态

    1. 直接取走大小为1的石堆
    2. 直接取走大小超过1的石堆中的一颗石子
    3. 将大小为1的石堆合并至大小超过1的石堆
    4. 合并两个大小超过1的石堆(不会影响操作次数)
    5. 将两个大小为1的石堆合并为1个石堆
      根据5个后继状态SG函数值求出该状态的SG函数值即可

    代码

    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #define rr register
    using namespace std;
    int sg[51][60011],Test;
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    inline signed min(int a,int b){return a<b?a:b;}
    inline signed dfs(int one,int sum){
    	if (~sg[one][sum]) return sg[one][sum];
    	if (!one) return sg[one][sum]=sum&1;
    	if (sum==1) return sg[one][sum]=dfs(one+1,0);//全都是1
    	rr int MEX=dfs(one-1,sum);
    	if (sum) MEX=min(MEX,dfs(one,sum-1));
    	if (one>1) MEX=min(MEX,dfs(one-2,sum+2+(sum>0)));//合并两堆大小为1的石子
    	if (sum) MEX=min(MEX,dfs(one-1,sum+1));//将大小为1的石堆与大小超过1的石堆合并
    	return sg[one][sum]=MEX^1;
    }
    signed main(){
    	memset(sg,-1,sizeof(sg)),Test=iut();
    	for (rr int i=1;i<=Test;++i){
    		rr int one=0,sum=0;
    		for (rr int T=iut();T;--T){
    			rr int x=iut();
    			if (x==1) ++one;
    			    else sum+=x+1;
    		}
    		sum-=(sum>0),dfs(one,sum);
    		printf("Case #%d: ",i);
    		puts(sg[one][sum]?"Alice":"Bob");
    	}
    	return 0;
    } 
    
  • 相关阅读:
    (8)ftp配置文档
    (6)centos安装和解压
    (8)python tkinter-画布
    (7)python tkinter-菜单栏
    (6)python tkinter-容器、子窗体
    (5)python tkinter-单选、多选
    bzoj1096 [ZJOI2007]仓库建设
    hdu3507 Print Article(斜率DP优化)
    bzoj1996 [Hnoi2010]chorus 合唱队
    跳石头
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/14622530.html
Copyright © 2020-2023  润新知