zoukankan      html  css  js  c++  java
  • 【BZOJ3895】取石子(博弈,记忆化搜索)

    题意:

    Alice和Bob两个好朋含友又开始玩取石子了。游戏开始时,有N堆石子排成一排,然后他们轮流操作(Alice先手),
    每次操作时从下面的规则中任选一个:
    1:从某堆石子中取走一个
    2:合并任意两堆石子
    不能操作的人输。Alice想知道,她是否能有必胜策略
    T<=100, N<=50. ai<=1000

    思路:From https://blog.csdn.net/sunshinezff/article/details/50893626?utm_source=blogkpcl10

       考虑如果不存在石子数为1的堆。
              设这种状态下操作数为x,显然x等于石子总数加操作数减1。
              可以证明当x为奇数时先手必胜。当x为偶数时先手必败。
              如果只有1堆石子,该结论显然成立。
              如果有多堆石子,每堆石子个数都大于1,并且x为偶数,下面我们证明这样先手必败。
              1.如果先手选择合并两堆石子,那么每堆石子的个数依然大于1,x变为奇数。
              2.如果先手选择从一堆石子数大于2的堆中拿走一枚石子,那么同上每堆石子个数依然大于1,x变为奇数。 
              3.如果先手选择从一堆石子数等于2的堆中拿走一枚石子,那么后手可以合并剩下的1枚石子到任意一个堆。
              那样x的奇偶性不变,每堆石子的个数依然大于1.
              综上所述,结论成立。
              然后考虑如果存在石子数为1的堆.我们设石子数为1的堆的个数为x,其余堆的个数为y.
              令f[x][y]为这种状态下先手必胜或是必败。
              每次转移枚举所有可能的操作。记忆化搜索即可。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<cmath>
     6 typedef long long ll;
     7 using namespace std;
     8 #define N   210000
     9 #define oo  10000000
    10 #define MOD 1000000007
    11 
    12 int f[60][51000];
    13  
    14 int dfs(int a,int b)
    15 {
    16     if(b==1) return dfs(a+1,0);
    17     if(a==0) return b&1;
    18     if(f[a][b]!=-1) return f[a][b];
    19     if(a&&!dfs(a-1,b)) return f[a][b]=1; //拿1
    20     if(a&&b&&!dfs(a-1,b+1)) return f[a][b]=1; //将1和大于1的合并
    21     if(a>=2&&!dfs(a-2,b+2+(b?1:0))) return f[a][b]=1; //合并2堆1
    22     if(b&&!dfs(a,b-1)) return f[a][b]=1; //合并2堆大于1的或拿1个大于1的 
    23     return f[a][b]=0;
    24 }
    25 
    26 int main()
    27 { 
    28     memset(f,-1,sizeof(f));
    29     int cas;
    30     scanf("%d",&cas); 
    31     while(cas--)
    32     {
    33         int n;
    34         scanf("%d",&n);
    35         int a=0; 
    36         int b=-1;
    37         for(int i=1;i<=n;i++)
    38         {
    39             int x;
    40             scanf("%d",&x);
    41             if(x==1) a++;
    42              else b+=x+1;
    43         }
    44         b=max(b,0);
    45         if(dfs(a,b)) printf("YES
    ");
    46          else printf("NO
    ");
    47     }
    48     return 0;
    49 }
    50     
  • 相关阅读:
    java架构之路-(面试篇)Mysql面试大全
    web工程的路径问题详解
    SQL知识点总结
    Mybatis简介
    mysql大全
    配置心得
    spring4.1.3+springmvc+mybatis3.2.1整合
    jstl标签
    jstl标签库
    Java并发控制机制
  • 原文地址:https://www.cnblogs.com/myx12345/p/9955423.html
Copyright © 2011-2022 走看看