LightOJ 1401 No More Tic-tac-toe(SG函数)

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

题意:一个字符串两个轮流在空闲的位置放置字母X或O,不允许出现两个连续的X或者两个连续的O。谁不能放谁输。

思路:记SG[n][a][b]为长为n的空串左右两侧的限制为a和b,0表示无限制,1表示这一侧不能放X,2表示这一侧不能放O。





const int INF=2000000000;

const int N=105;

int SG[N][3][3],C,num=0,n;

string s;



int OK(int i,char c,string s,int a,int b)

{

    int L=0,R=Len(s)-1;

    if(i==L)

    {

        if(c=='X'&&a==1||c=='O'&&a==2) return 0;

        if(R>L)

        {

            if(s[i+1]==c) return 0;

            return 1;

        }

        else

        {

            if(c=='X'&&b==1||c=='O'&&b==2) return 0;

            return 1;

        }

    }

    else if(i==R)

    {

        if(c=='X'&&b==1||c=='O'&&b==2) return 0;

        if(R>L)

        {

            if(s[i-1]==c) return 0;

            return 1;

        }

        else

        {

            if(c=='X'&&a==1||c=='O'&&a==2) return 0;

            return 1;

        }

    }

    else

    {

        if(c==s[i-1]||c==s[i+1]) return 0;

        return 1;

    }

}



int DFS(string,int,int);



int getSG1(string s,int a,int b)

{

    int n=Len(s);

    if(SG[n][a][b]!=-1) return SG[n][a][b];

    return SG[n][a][b]=DFS(s,a,b);

}



int getSG(string s,int a,int b)

{

    int ans=0,L=a,R,i,n=Len(s);

    string s1="";

    for(i=0;i<=n;i++)

    {

        if(i<n&&s[i]=='.') s1+=s[i];

        else

        {

            if(Len(s1)==0)

            {

                if(i==n);

                else if(s[i]=='X') L=1;

                else L=2;

                continue;

            }

            if(i==n) R=b;

            else if(s[i]=='X') R=1;

            else R=2;

            ans^=getSG1(s1,L,R);

            s1="";

            L=R;

        }

    }

    return ans;

}



int DFS(string s,int a,int b)

{

    int p[300]={0},i,n=Len(s);

    FOR0(i,n) if(s[i]!='X'&&s[i]!='O')

    {

        if(OK(i,'X',s,a,b))

        {

            s[i]='X';

            p[getSG(s,a,b)]=1;

            s[i]='.';

        }

        if(OK(i,'O',s,a,b))

        {

            s[i]='O';

            p[getSG(s,a,b)]=1;

            s[i]='.';

        }

    }

    for(i=0;p[i];i++);

    return i;

}



int main()

{

    clr(SG,-1);

    RD(C);

    while(C--)

    {

        RD(s);

        n=Len(s);

        int i,cnt=0;

        FOR0(i,n) if(s[i]!='.') cnt++;

        int p=DFS(s,0,0);

        printf("Case %d: ",++num);

        if(cnt%2&&p||cnt%2==0&&!p) puts("No");

        else puts("Yes");

    }

    return 0;

}

  

你可能感兴趣的:(more)