博弈论初级逗比题:poj2484 && poj2975 && poj2505

博弈论初初级

 

 


1:poj2484 A FUNNY GAME

  题目大意:

    给N个围成一圈的硬币,设编号为1到n,两个杀马特的逗比轮流取,每次可以取走一个硬币,或两个

  编号相邻的硬币,问对于给出的N,哪个逗比赢。

 

  解析题目:

    乍一看好像特别牛鼻,实际先取的逗比只要不能一下子全部取完,那么稳输= = ,因为这是一张对称

  的图,只要后取能做到取完后是一张中心对称的图,就稳赢,当然前提是先取的取不完。

    所以只有N为1 or 2 时先取的赢,其余稳输。

 

  代码:

  
#include<cstdio>
char ch1, ch2;
int main ( )
{
    while (1)
    {
        ch1=getchar(), ch2=getchar();
        if (ch1=='0') break;
        if (ch2=='\n'&&ch1<='2')printf("Alice\n"); else printf("Bob\n");
        while (ch2!='\n') ch2=getchar();
    }
}
poj2484

 


 

2:poj2975 Nim游戏

  题目大意:

    给你N堆石子,告诉你每堆石子中石子的个数,又来了两个杀马特的逗比,他们轮流取,每次可以取任

  意一堆石子的任意数量,最后哪个逗比没得取就为输。问先取的是否有必胜的方法?有几种?

 

  题目解析:

    将每堆石子的石子数异或在一起,如果大于零,就代表存在必胜的方法:先取一堆石子使得异或和变为

  零,即对方面临的是败态,然后根据它的取数保持石子数的异或和为零,最后就赢了。也就是说只有第一步

  可选,方案总数即为第一方案的总数。分别将每堆石子的数量异或回去,看石子数和异或和的大小关系即

  可判断可不可取。

 

  代码:

  
 1 #include<cstdio>
 2 int n,he,an,a[1004],i;
 3 int main ( )
 4 {
 5     while (scanf("%d",&n)!=EOF&&n)
 6     {
 7         he = 0, an = 0;
 8         for (i=1; i<=n; i++) scanf("%d",&a[i]),he^=a[i];
 9         if  (!he) { printf("0\n"); continue; }
10         for (i=1; i<=n; i++) if  ((he^a[i]) <= a[i]) an++;
11         printf("%d\n",an);
12     }
13 }
poj2975

 


 

3:poj2505 一个垒乘的游戏

  题目大意:

    给出一个N,两个杀马特的逗比从同一个1开始,每次可以把这个数乘2~9中的任意数,最后先乘到>=n

  的胜。

 

  题目解析:

    倒推:比如轮到一个逗比时这个数已经>=N了,那么这个逗比就输了,也就是说面临[n,+无穷大)的必

  定败,那么如果倒退一步操作,也就是说对于这个数,你能通过乘鱼2~9中的一个数使它达到上述区间,那

  么这个数就是一个必胜数,比如n-1,随便乘都能达到上述区间,这个区间的上限是n-1,但下限呢 ?就是

  [(n-1)/ 9 ]+1;

    倒退的过程就是:

      由开始的比败区间[n,+无穷大)    推出   上一个必胜区间,   再通过当前必胜区间推出上一个必

  败区间,最后看1 属于哪个区间即可判断先手必败还是必胜。

 

  代码:

  
 1 #include<cstdio>
 2 long long n,f,i,l;
 3 int main ( )
 4 {
 5     while (scanf("%I64d",&n)!=EOF)
 6     {    
 7         f = 0,i = 1, l= 9;
 8         while (i<n) i*=l, l=18/l, f=1-f;
 9         if  (f) printf("Stan wins.\n");
10         else    printf("Ollie wins.\n");
11     }
12 }
poj2505

 


END。

 

 

  

 

posted @ 2013-12-31 11:49  哥少先队的  阅读(175)  评论(0编辑  收藏  举报