[博弈]

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[博弈]相关的知识,希望对你有一定的参考价值。

http://blog.sina.com.cn/s/blog_83d1d5c70100y9yd.html

----很好的一篇sg函数资料,可惜不是sina用户转载不了.

 

hdu1846(记忆化搜索)

技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int cas,n,m;
int sg[1010];
int dfs(int x)
{
  if(x<=m)return sg[x]=1;
  if(sg[x]!=-1)return sg[x];
  for(int i=1;i<=m;i++)
   if(dfs(x-i)==0)return sg[x]=1;
  return sg[x]=0; 
}
int main()
{
  scanf("%d",&cas);
  while(cas--)
  {
    scanf("%d%d",&n,&m);
    memset(sg,-1,sizeof(sg));
    if(dfs(n)==1)printf("first\\n");else printf("second\\n");
    //for(int i=1;i<=n;i++)printf("%d %d\\n",i,sg[i]);
  }
}
View Code

hdu2188(和上题差不多)

技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int cas,n,m;int sg[10100];
int dfs(int x)
{
  if(sg[x]!=-1)return sg[x];
  if(x+m>=n)return sg[x]=1;
  for(int i=1;i<=m;i++)
   if(dfs(x+i)==0)return sg[x]=1;
  return sg[x]=0; 
}
int main()
{
  scanf("%d",&cas);
  while(cas--)
  {
    scanf("%d%d",&n,&m);
    memset(sg,-1,sizeof(sg));
    if(dfs(0)==1)printf("Grass\\n");else printf("Rabbit\\n");
  }
}
View Code

 

取火柴问题 blog传送门:http://acm.hdu.edu.cn/forum/read.php?fid=9&tid=10617

定理实在太多了...blahblah...感觉自己最多只能沦为背背背选手..

预热题:

hdu1847(极短的代码)

每个人每次抓的牌只能是2的幂次.kiki先手

当只剩下三张牌时,先手必败.每一个数-1或-2都可以变成三的倍数,对于这一点要有足够的敏感度....想不到,回去面壁思过QAQ

所以当n为3的倍数时,kiki如果取走一点,cici都可以构造三的倍数,先手必败;

若n不为3的倍数,kiki可以把它构造成3的倍数,十分轻易.

 

#include<cstdio>
#include<algorithm>
using namespace std;
int cas,n;
int main()
{
  while(scanf("%d",&n)!=EOF)
  {
    if(n%3==0)printf("Cici\\n");else printf("Kiki\\n");
  }
}

 

 

hdu1848 Fibonacci again and again

解题报告传送门:http://wenku.baidu.com/link?url=fVbzcnAnOOahfzy0Dk6YDuqYWFhRdsCrlfQ7J8E6G4ht_xAxggT9fMfFn6QJGnKag7aEhV_j7mzeB3v89cTsF_KXVTNi0mlIan6kzZHrA_q

先给出结论,这里要用到位运算,异或:^

    游戏的某个位置(x1,x2,x3) x1,x2,x3表示3堆的个数。当且仅当 x1^x2^x3=0时,此点才是必败点P;

    结论可以推广到一般情况,即有n堆,(x1,x2,x3,...xn) 当且仅当x1^x2^x3...^xn=0时,此点才是必败点P;

 

最后看下组合博弈,就是把简单的游戏组合起来,比如3堆的可以看成3个一堆的游戏。

 定理:

假设游戏 Gi的SG函数是gi, i=1,…,n, 则
G = G1 + … + Gn 的 SG函数是
g(x1,…,xn) = g1(x1)⊕…⊕gn(xn).

其中那个符号就是异或^

技术分享
#include<cstdio>
#include<cstring> 
#include<algorithm>
using namespace std;
int f[1001];
int sg[1001];int b[1010];
int m,n,p;
int main()
{
  f[1]=1;f[2]=2;
  sg[0]=0;sg[1]=1;sg[2]=2;sg[3]=3;
  for(int i=3;f[i-1]<=1000;i++)
    f[i]=f[i-1]+f[i-2];
  for(int i=4;i<=1000;i++)
  {
    sg[i]=i;memset(b,0,sizeof(b));
    for(int j=0;f[j]<=i;j++)
     b[sg[i-f[j]]]=1;//遍寻i所能到达点集的sg值 
    for(int j=0;j<20;j++)
    {
      if(b[j]==0){sg[i]=j;break;} //找最小的未出现的sg值 
    }   
  }  
  while(scanf("%d%d%d",&m,&n,&p),(m!=0||n!=0||p!=0))
  {
    if((sg[n]^sg[m]^sg[p])==0)printf("Nacci\\n"); 
    else printf("Fibo\\n");
  }return 0;
}
View Code

吐槽:hdu的多组数据真是坑...........还有,原来^的优先级这么低!!!

 

2333感觉今天做了套杭电博弈专场.

 

以上是关于[博弈]的主要内容,如果未能解决你的问题,请参考以下文章

HDU 1847(博弈)

只用一行代码就能搞定,博弈论究竟是什么神仙算法?

博弈论

基础博弈

“要有足够的耐心,一点一滴地改变世界”

前端开发进阶手册.pdf