zoukankan      html  css  js  c++  java
  • 博弈 取石子

    题目链接:http://acm.bupt.edu.cn/onlinejudge/newoj/showProblem/show_problem.php?problem_id=65

    Description

         champ最近在和dalong玩一个取石子游戏,游戏规则很简单:有三堆石子,两人轮流取,每次任选两堆石子,然后从一堆中取走x(x>=1)个石子,另一堆中取走2*x个石子,最后不能取者输掉游戏,champ每一次都先取。
         现在,champ告诉你初始三堆石子的数量,他想知道,自己是否有必胜的策略。你可以假定champ和dalong都足够聪明,每次都会选择最优的策略。



    Input
    多组测试数据
    每行3个正整数(范围[0,255]),表示最初三堆石子的数量。
    0 0 0表示输入结束。这组数据不用处理


    Output
    每组输出一行
    如果champ有必胜策略,那么输出"champ",否则输出"dalong"。(注意,引号不要输出)


    Sample Input

    1 2 0
    1 4 1
    0 0 0



    Sample Output

    champ
    dalong
    这个题用博弈来解决,我们用数组sg[x][y][z]来表示这个状态是P或者N,如果我们直接搜索博弈树,根据PN规则,从上到下搜索所有的子局面,
    根据他们的PN得出现在的状态,时间复杂度为(n^4),由于组成的有向图是无环的(因为每次都是减少的),所以我们从下往上扩展。
    对于一个状态a,b,c若它是P,则扩展的到任何可能的状态都是N,这样负责度为(n^3+ 失败点个数*n).
    代码如下:
    #include <iostream>
    #include <stdio.h>
    using namespace std;
    const int N=256;
    bool sg[N][N][N];
    int x,y,z;
    void exchange(int &a,int &b,int &c)
    {
     int tmp;
     if(a>b)
     {
      tmp=b;
      b=a;
      a=tmp;
     }
     if(b>c)
     {
      tmp=c;
      c=b;
      b=tmp;
     }
     if(a>b)
     {
      tmp=b;
      b=a;
      a=tmp;
     }
    }
    void init()
    {
     int i,j,k,t,a,b,c;
     for(i=0;i<N;i++)
      for(j=0;j<N;j++)
       for(k=0;k<N;k++)
        sg[i][j][k]=0;
     for(i=0;i<N;i++)
     {
      for(j=i;j<N;j++)
      {
       for(k=j;k<N;k++)
       {
        if(!sg[i][j][k])
        {
         //扩展i,j
         for(t=1;(i+t<N && j+2*t<N);t++)
         {
          a=i+t;
          b=j+2*t;
          c=k;
          exchange(a,b,c);
          sg[a][b][c]=1;
         }
         for(t=1;(i+2*t<N && j+t<N);t++)
         {
          a=i+2*t;
          b=j+t;
          c=k;
          exchange(a,b,c);
          sg[a][b][c]=1;
         }
         //扩展i,k
         for(t=1;(i+t<N && k+2*t<N);t++)
         {
          a=i+t;
          b=j;
          c=k+2*t;
          exchange(a,b,c);
          sg[a][b][c]=1;
         }
         for(t=1;(i+2*t<N && k+t<N);t++)
         {
          a=i+2*t;
          b=j;
          c=k+t;
          exchange(a,b,c);
          sg[a][b][c]=1;
         }
         //扩展j,k
         for(t=1;(j+t<N && k+2*t<N);t++)
         {
          a=i;
          b=j+t;
          c=k+2*t;
          exchange(a,b,c);
          sg[a][b][c]=1;
         }
         for(t=1;(j+2*t<N && k+t<N);t++)
         {
          a=i;
          b=j+2*t;
          c=k+t;
          exchange(a,b,c);
          sg[a][b][c]=1;
         }
        }
       }
      }
     }
    }
    int main()
    {
     init();
     while(1)
     {
      scanf("%d%d%d",&x,&y,&z);
      if(!x && !y && !z)
       break;
      exchange(x,y,z);
      if(sg[x][y][z])
       printf("champ\n");
      else
       printf("dalong\n");
     }
     return 0;
    }
  • 相关阅读:
    SQL 分页存储
    ubuntu下删除openjdk,改用sun jdk
    LCD 驱动的整体分析。
    关于IT行业人员吃的都是青春饭?[透彻讲解]
    【转载】I.MX25上摄像头调试总结
    wifi 移植
    函数指针的透彻分析
    关于module_param()宏 (转)
    problem with aptget update ubuntu 11.10
    YUV 格式讲解
  • 原文地址:https://www.cnblogs.com/buptLizer/p/2163501.html
Copyright © 2011-2022 走看看