zoukankan      html  css  js  c++  java
  • hdu 4111 Alice and Bob(中档博弈题)

    copy VS study

    1.每堆部是1的时候,是3的倍数时输否则赢;

    2.只有一堆2其他全是1的时候,1的堆数是3的倍数时输否则赢;

    3.其他情况下,计算出总和+堆数-1,若为偶数,且1的堆数是偶数,则一定输;

    4.不在上述情况下则赢。

    #include<stdio.h>
    int main()
    {
        int js=0;
        int _case,i,n,x;
        int flag1,flag2,flag,sum;
        scanf("%d",&_case);
        while(_case--)
        {
            js++;
            flag1=0;
            flag2=0;
            flag=0;
            sum=0;
            scanf("%d",&n);
            for(i=0;i<n;i++)
            {
                scanf("%d",&x);
                sum+=x;
                if(x==1)flag1++;
                else if(x==2)flag2++;
            }
            if(flag1==n)
            {
                if(flag1%3==0)flag=1;
            }
            else if(flag1==n-1&&flag2==1)
            {
                if(flag1%3==0)flag=1;
            }
            else
            {
                if((sum+n-1)%2==0&&flag1%2==0)
                flag=1;
            }
            printf("Case #%d: ",js);
            if(flag)printf("Bob
    ");
            else printf("Alice
    ");
        }
        return 0;
    }

    转载:

    题意:有N堆石头,可以把两堆合成一堆,也可以把一堆去掉一个。

    由于总数不变,最终总是要一个个拿完。那么有机会获胜的一方,肯定是先要把所有的合在一起,那么最终就拼奇偶数了。所以双方都要合并。总共就是sigma(ai)+n-1。

    而且如果没有某堆只有一个的话,对方是阻挡不住的,没有取完,便被合并了。

    所以就要考虑某堆只有一个的情况,单独考虑。

    其中的操作包括:

    把某堆只有一个的,取走

    把两堆只有一个的,合并

    把某堆只有一个的,合并给不是一个的

    把不是一个的,取走一个

    采用记忆化搜索

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define N 10005
    #define LL long long
    #define inf 1<<29
    #define eps 1e-7
    using namespace std;
    int sg[55][60005];
    int get_sg(int i,int j)
    {
        if(sg[i][j]!=-1)
            return sg[i][j];
        if(j==1)
            return sg[i][j]=get_sg(i+1,0);
        sg[i][j]=0;
        //某堆只有一个的取掉
        if(i>=1&&!get_sg(i-1,j))
            sg[i][j]=1;
        //把不是1个的取走一个
        else if(j>=1&&!get_sg(i,j-1))
            sg[i][j]=1;
        //把1个的合并给不是1个的
        else if(i>=1&&j>0&&!get_sg(i-1,j+1))
            sg[i][j]=1;
        //把两个1个的合并,其中注意,合并是需要一步的
        else if(i>=2&&((j==0&&!get_sg(i-2,j+2))||(j&&!get_sg(i-2,j+3))))
            sg[i][j]=1;
        return sg[i][j];
    }
    int main()
    {
        int n,t,cas=0,k;
        scanf("%d",&t);
        memset(sg,-1,sizeof(sg));
        while(t--)
        {
            scanf("%d",&n);
            int one=0,sum=0;
            while(n--)
            {
                scanf("%d",&k);
                if(k==1)
                    one++;
                else
                    sum+=(k+1);
            }
            if(sum)
                sum--;
            printf("Case #%d: ",++cas);
            if(get_sg(one,sum))
                puts("Alice");
            else
                puts("Bob");
        }
        return 0;
    }

    至此SG函数应该算是了解掌握了;

    不过学ACM之初没有好好练习搜索,

    以致目前仍然不能熟练的打SG表。Orz

  • 相关阅读:
    博客园首页CSS模板
    style、currentStyle、getComputedStyle的区别和用法
    createDocumentFragment创建文档碎片节点
    setTimeout里如果有$(this),$(this)指的是谁?
    让ie也兼容placeholder
    eval()函数可以把一个字符串当作一个JavaScript表达式一样去执行它
    遮罩层特效(根据鼠标进入离开方向出现)
    jquery之attr和prop区别
    js封装类简单举例
    自动换行 word-break:break-all和word-wrap:break-word
  • 原文地址:https://www.cnblogs.com/XDJjy/p/3350014.html
Copyright © 2011-2022 走看看