zoukankan      html  css  js  c++  java
  • 基础博弈专题

    感觉,目前主要是能够将具体的题目转化为某一种博弈类型,这样根据类型来做,会好很多。

    首先,是比较基础的

    巴什博奕(Bash Game):

    根据这三个性质去推理的话,下面这几道题目应该可以很快解决

    (1) 所有终结点是必败点(P点);
     
    (2) 从任何必胜点(N点)操作,至少有一种方法可以进入必败点(P点);
     
    (3)无论如何操作, 从必败点(P点)都只能进入必胜点(N点).
    hdu1846
    #include<iostream>
    using namespace std;
    int main()
    {
        int n,m,cas;
        scanf("%d",&cas);
        while(cas--)
        {
            scanf("%d %d",&n,&m);
            if(n<=m)
                puts("first");
            else if(n%(m+1)==0)
                puts("second");
            else puts("first");
        }
        return 0;
    }
    

     hdu 2147

    #include<iostream>
    using namespace std;
    int main()
    {
        int n,m;
        while(scanf("%d %d",&n,&m)==2&&(n||m))
        {
            if(n%2==1 && m%2==1)
                puts("What a pity!");
            else puts("Wonderful!");
        }
        return 0;
    }
    

     hdu2149

    #include<iostream>
    using namespace std;
    int main()
    {
        int m,n;
        while(scanf("%d %d",&m,&n)==2)
        {
            if(n>=m)
            {
                for(int i=m;i<n;i++)
                    printf("%d ",i);
                printf("%d\n",n);
                continue;
            }
            int flag=0;
            for(int i=1;i<=n;i++)
            {
                if(m-i<=n)
                    continue;
                if((m-i)%(n+1)==0)
                {
                    if(!flag)
                        printf("%d",i),flag=1;
                    else printf(" %d",i);
                }
            }
            if(flag)puts("");
            else puts("none");
        }
        return 0;
    }
    

     hdu2188

    #include<iostream>
    using namespace std;
    int main()
    {
        int n,m,cas;
        scanf("%d",&cas);
        while(cas--)
        {
            scanf("%d %d",&n,&m);
            if(n<=m)
            {
                puts("Grass");
                continue;
            }
            if(n%(m+1)==0)
                puts("Rabbit");
            else puts("Grass");
        }
        return 0;
    }
    

     接下来是

    (二)威佐夫博奕(Wythoff Game):有两堆各若干个物品,两个人轮流从某一堆或同
    时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜。

    嘿嘿,没做过类型的题目。
    再接下来,是
    比较重点的

    (三)尼姆博奕(Nimm Game):有三堆各若干个物品,两个人轮流从某一堆取任意多的
    物品,规定每次至少取一个,多者不限,最后取光者得胜。

    主要涉及到了异或操作,关于这方面,感觉这篇博文介绍的还不错http://blog.sina.com.cn/s/blog_8f06da990100uwl1.html

    hdu1849

    #include<iostream>
    #include<algorithm>
    using namespace std;
    int main()
    {
    	int a,n;
    	while(scanf("%d",&n)==1 && n)
    	{
    		a=0;
    		int b;
    		for(int i=0;i<n;i++)
    		{
    			scanf("%d",&b);
    			a^=b;
    		}
    		if(a!=0)
    			puts("Rabbit Win!");
    		else puts("Grass Win!");
    	}
    	return 0;
    }
    

     hdu1850

    #include<stdio.h>
    int main()
    {
        int n,s[110],i,sum,count;
        while(scanf("%d",&n)!=EOF&&n)
        {
            sum=0;count=0;
            for(i=0;i<n;i++)
            {
                scanf("%d",&s[i]);
                sum=sum^s[i];
            }
            for(i=0;i<n;i++)
            {
                if(s[i]>(sum^s[i]))
                    count++;
            }
            printf("%d\n",count);
        }
        return 0;
    }
    

     再接下来就是博弈的经典所在了,关于sg函数

    同样,在上面的博文里面介绍的很详细了

    hdu1848 ( Fibonacci again and again )  sg函数与Nim博弈的组合

    #include<iostream>
    #include<algorithm>
    using namespace std;
    int fib[1010],a[20],hash1[1010],sg[1010];
    void init()
    {
        a[0]=a[1]=1;
        a[2]=2;
        memset(fib,0,sizeof(fib));
        fib[1]=fib[2]=1;
        for(int i=3;a[i-1]<=1000;i++)
        {
            a[i]=a[i-1]+a[i-2];
            fib[a[i]]=1;
        }
    }
    void Get_sg()
    {
        for(int i=0;i<=3;i++)
            sg[i]=i;
        for(int i=4;i<=1000;i++)
        {
            memset(hash1,0,sizeof(hash1));
            for(int j=1;j<=i;j++)
                if(fib[j])
                    hash1[sg[i-j]]=1;
            for(int k=0;k<=i;k++)
                if(!hash1[k])
                {
                    sg[i]=k;
                    break;
                }
        }
    }
    int main()
    {
        init();
        Get_sg();
        int n,m,p;
        while(scanf("%d %d %d",&n,&m,&p)==3&& (m||n||p))
        {
            if((sg[n]^sg[m]^sg[p])!=0)
                puts("Fibo");
            else puts("Nacci");
        }
        return 0;
    }
    
  • 相关阅读:
    with check option(视图 )
    @@ERROR
    事务处理
    含有自增序列的表中使用truncate与delete的不同结果
    Oracle中的通配符
    Java方法重载
    java递归方法
    Oracle中的for语句
    Uboot 2014.07 makefile分析
    linux内核目录结构
  • 原文地址:https://www.cnblogs.com/nanke/p/2245183.html
Copyright © 2011-2022 走看看