URAL 1540 Battle for the Ring

由于有多条链,每条链可以单独作为一个游戏,最后把sg值亦或起来就可以判断胜负。

对于每条链,选定第k个后,会分成若干条链,每条链可以递归的求sg值。

选择某个ring之后分成若干条链,是走了一步,这些链的sg值应该亦或起来,作为选择某个ring之后得到的sg值。

由于选择不同的ring会有不同的结果,所以选择不同的ring得到的sg值应该保存起来,然后原链的sg值去最小未出现sg值就行。



这题的重点在于要给出第一步的位置。

首先已知所有链亦或后的sg值,也就是判断胜负的as。

对于每一条链,先用as亦或该链的sg值,相当于抛出去该链。

然后对于该链,枚举每一个ring的位置,得到该位置的sg值tmp。

如果tmp^as==0,代表该位置是使得后手必胜的位置,也就得到答案。

最后别忘了as亦或该链的sg值,相当于在结果中包括该链。


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int dp[60][110][110];
int a[60][110],id;
int s[110],top;
void dfs(int l,int r){
    int &as=dp[id][l][r];
    if(as!=-1)return ;
    as=0;
    if(l>r)return ;
    int i,k,st,ed,sg;
    for(k=l;k<=r;k++){
        st=-1;
        for(i=l;i<=r;i++){
            if(a[id][i]<=a[id][k]&&st!=-1){
                ed=i-1;
                dfs(st,ed);
                st=-1;
            }
            if(a[id][i]>a[id][k]&&st==-1)
                st=i;
        }
        if(st!=-1){
            ed=i-1;
            dfs(st,ed);
            st=-1;
        }
    }
    top=0;
    for(k=l;k<=r;k++){
        st=-1;
        sg=0;
        for(i=l;i<=r;i++){
            if(a[id][i]>a[id][k]&&st==-1)
                st=i;
            if(a[id][i]<=a[id][k]&&st!=-1){
                ed=i-1;
                sg^=dp[id][st][ed];
                st=-1;
            }
        }
        if(st!=-1){
            ed=i-1;
            sg^=dp[id][st][ed];
            st=-1;
        }
        s[top++]=sg;
    }
    sort(s,s+top);
    top=unique(s,s+top)-s;
    for(i=0;i<top;i++)
        if(s[i]==as)
            as++;
        else
            break;
}

int main(){
    int i,j,k,n,m,as=0;
    int tmp,st,ed;
    memset(dp,-1,sizeof(dp));
    scanf("%d",&n);
    for(id=1;id<=n;id++){
        scanf("%d",&m);
        for(i=1;i<=m;i++)
            scanf("%d",&a[id][i]);
        a[id][0]=m;
        dfs(1,m);
        as^=dp[id][1][m];
    }
    if(as==0){puts("S");return 0;}
    for(id=1;id<=n;id++){
        m=a[id][0];
        as^=dp[id][1][m];
        for(k=1;k<=m;k++){
            tmp=0;
            st=-1;
            for(i=1;i<=m;i++){
                if(a[id][i]>a[id][k]&&st==-1)
                    st=i;
                if(a[id][i]<=a[id][k]&&st!=-1){
                    ed=i-1;
                    tmp^=dp[id][st][ed];
                    st=-1;
                }
            }
            if(st!=-1){
                ed=i-1;
                tmp^=dp[id][st][ed];
                st=-1;
            }
            if((as^tmp)==0)break;
        }
        as^=dp[id][1][m];
        if(k<=m)break;
    }
    printf("G\n%d %d\n",id,k);

    return 0;
}





你可能感兴趣的:(URAL 1540 Battle for the Ring)