LightOJ 1229 Treblecross(SG函数)

题目链接:http://lightoj.com/volume_showproblem.php?problem=1229

题意:一排n个位置,有些位置已经放上了字母X,剩下的是空的。两人轮流放置X在空的位置。放置后出现连续3个X的赢。问先手是否有必胜策略?若有,可以放在哪些地方?

思路:枚举每个空的位置作为先手放置X的位置,然后判断是否能赢。这样,就会出现一些连续的空闲位置,求这些空闲位置的SG和。



const int INF=2000000000;
const int N=10005;
int SG[N];
int C,num=0;
string s;

int DFS(int x)
{
    if(x<0) return 0;
    if(SG[x]!=-1) return SG[x];
    int a[300]={0},i;
    FOR1(i,x) a[DFS(i-3)^DFS(x-i-2)]=1;
    for(i=0;a[i];i++);
    return SG[x]=i;
}

int OK(int pos)
{
    string s1=s;
    int i,j,L=Len(s1);
    if(s1[pos]=='X') return 0;
    s1[pos]='X';
    for(i=0;i+2<L;i++) if(s1[i]=='X'&&s1[i+1]=='X'&&s1[i+2]=='X')
    {
        return 1;
    }
    FOR0(i,L)
    {
        if(i+1<L&&s1[i]=='X'&&s1[i+1]=='X') return 0;
        if(i+2<L&&s1[i]=='X'&&s1[i+2]=='X') return 0;
    }
    int ans=0,a=2,b=0,k;
    FOR0(i,L) if(s1[i]=='X') k=i;
    FOR0(i,L)
    {
        if(i>k) a=0;
        if(s1[i]=='X')
        {
            b=2;
            continue;
        }
        for(j=i;s1[j]=='.';j++);
        ans^=DFS(j-i-a-b);
        i=j-1;
    }
    return !ans;
}

int main()
{
    clr(SG,-1);
    RD(C);
    while(C--)
    {
        vector<int> a;
        int i;
        RD(s);
        FOR0(i,Len(s)) if(OK(i)) a.pb(i);
        printf("Case %d: ",++num);
        if(SZ(a)==0) puts("0");
        else
        {
            FOR0(i,SZ(a)-1) printf("%d ",a[i]+1);
            printf("%d\n",a[i]+1);
        }
    }
    return 0;
}

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值