CF919F A Game With Numbers

题目:(luogu翻译错的很多)

Alice和Bob玩游戏,每人有8张牌,牌的值为0~4。每一轮当前玩家选择自己的牌A和对手的牌B,然后将A的值变为( A + B )%5,其中A和B都不是0。

当一个人手牌全为0时他就赢了。

T(T<=1e5)组询问,求最后谁赢了,如果都没赢输出Deal。(两个人都是最优方案)

题解:

博弈搜索。

只不过本题有无解情况,因此dfs会卡(应该是我太弱了)。所以考虑用bfs,相当于dfs中直接回溯。

代码:

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int num[10][10][10][10],cnt;
int T;
int dp[250000],ind[250000];//first:second
void init()
{
    for(int a=0;a<=8;a++)
        for(int b=0;a+b<=8;b++)
            for(int c=0;a+b+c<=8;c++)
                for(int d=0;a+b+c+d<=8;d++)
                    num[a][b][c][d]=++cnt;
}
int tn(int a,int b)
{
    return (a-1)*cnt+b-1;
}
int cg(int a[5],int b[5])
{
    return tn(num[a[1]][a[2]][a[3]][a[4]],num[b[1]][b[2]][b[3]][b[4]]);
}
int gt(int a[5])
{
    int ret = 0;
    for(int i=1;i<=4;i++)ret+=(a[i]!=0);
    return ret;
}
struct node
{
    int a[5],b[5];
    int aa(){return num[a[1]][a[2]][a[3]][a[4]];}
    int bb(){return num[b[1]][b[2]][b[3]][b[4]];}
    int cc(){return tn(aa(),bb());}
    node df()
    {
        node ret;
        for(int i=0;i<=4;i++)ret.a[i]=b[i],ret.b[i]=a[i];
        return ret;
    }
}tmp;
queue<node>q;
int a0[5],b0[5];
void dfsb(int dep,int sum)
{
    if(dep==5)
    {
        int c = cg(a0,b0),ga=gt(a0),gb=gt(b0);
        ind[c] = ga*gb;
        if(!(ga*gb))
        {
            if(!ga)dp[c]=1;
            else dp[c]=2;
            tmp.a[0]=8-a0[1]-a0[2]-a0[3]-a0[4],tmp.a[1]=a0[1],tmp.a[2]=a0[2],tmp.a[3]=a0[3],tmp.a[4]=a0[4];
            tmp.b[0]=8-b0[1]-b0[2]-b0[3]-b0[4],tmp.b[1]=b0[1],tmp.b[2]=b0[2],tmp.b[3]=b0[3],tmp.b[4]=b0[4];
            q.push(tmp);
        }
        return ;
    }
    for(b0[dep]=0;b0[dep]+sum<=8;b0[dep]++)
        dfsb(dep+1,sum+b0[dep]);
}
void dfsa(int dep,int sum)
{
    if(dep==5){dfsb(1,0);return ;}
    for(a0[dep]=0;a0[dep]+sum<=8;a0[dep]++)
        dfsa(dep+1,sum+a0[dep]);
}
void bfs()
{
    while(!q.empty())
    {
        tmp = q.front();
        q.pop();
        node v = tmp.df();
        for(int j=1;j<=4;j++)
        {
            if(!v.b[j])continue;
            for(int i=0;i<=4;i++)
            {
                if(!v.a[i]||(i-j+5)%5==0)continue;
                v.a[i]--;
                v.a[(i-j+5)%5]++;
                int c = v.cc(),c0 = tmp.cc();
                if(!ind[c])
                {
                    v.a[i]++;
                    v.a[(i-j+5)%5]--;
                    continue;
                }
                if(dp[c0]==2)
                {
                    dp[c]=1;
                    ind[c]=0;
                    q.push(v);
                    v.a[i]++;
                    v.a[(i-j+5)%5]--;
                    continue;
                }else if(!dp[c0])
                {
                    dp[c]=3;
                }
                ind[c]--;
                v.a[i]++;
                v.a[(i-j+5)%5]--;
                if(ind[c])continue;
                if(!dp[c])dp[c]=2;
                else dp[c]=0;
                v.a[i]--;
                v.a[(i-j+5)%5]++;
                q.push(v);
                v.a[i]++;
                v.a[(i-j+5)%5]--;
            }
        }
    }
}
int typ;
int main()
{
    init();
    dfsa(1,0);
    bfs();
    scanf("%d",&T);
    while(T--)
    {
        memset(a0,0,sizeof(a0));
        memset(b0,0,sizeof(b0));
        scanf("%d",&typ);
        for(int x,i=1;i<=8;i++)
        {
            scanf("%d",&x);
            a0[x]++;
        }
        for(int x,i=1;i<=8;i++)
        {
            scanf("%d",&x);
            b0[x]++;
        }
        int c = typ?cg(b0,a0):cg(a0,b0);
        int ans = dp[c];
        if(!ans)
        {
            printf("Deal\n");
        }else
        {
            if((ans-1)^typ)
            {
                printf("Bob\n");
            }else
            {
                printf("Alice\n");
            }
        }
    }
    return 0;
}

 

posted @ 2018-10-24 16:51  LiGuanlin  阅读(362)  评论(10编辑  收藏  举报