zoukankan      html  css  js  c++  java
  • 小乐乐吃糖豆

    小乐乐吃糖豆

    ​ 小乐乐是一个比较喜欢吃糖豆的小孩子,小乐乐的哥哥大乐乐也同样爱吃糖豆。

    作为一个小孩子,他们永远觉得谁吃掉了最后一个糖豆,谁吃的糖豆最多。

    为了公平起见小乐乐与大乐乐商量吃糖豆的规则如下:

    1. 小乐乐与大乐乐轮流吃糖豆。  
      
    2. 小乐乐作为弟弟,小乐乐先吃糖豆。  
      
    3. 小乐乐第一次可以吃任意不超过n 个糖豆。(n为糖豆初始总数)  
      
    4. 后一个人每次能吃【1,前一个人吃的糖豆*2】  
      

    ​ > 已知有n个糖豆,小乐乐与大乐乐开始分食糖豆,小乐乐与大乐乐都采用最优策略,请问谁能吃到最后一粒糖豆?

    分析:

    ​ 明显的博弈题,属于组合游戏的范畴,对于每个状态dp[i][j] 代表可以取1~i个糖果,还剩j个糖果的状态,

    如果这个状态的后继状态存在必输状态,那么这个状态则是必胜状态,否则是必输状态,

    剪枝操作

    1. j=0,是必输状态

    2. i>=j 是必胜状态

      if j是3的倍数取 1~(j%3-1)的糖果,否则 取1~(j%3)的糖果。

    因为处于你这个状态想要必胜,你就要尽力寻找后继为必输状态,其他取法部分可能存在后继为必输状态的。

    #include<cstdio>
    #include<algorithm>
    #include<string>
    #include<cstring>
    #include<iostream>
    #include<iomanip>
    #include<map>
    #include<vector>
    #define mset(a,b)   memset(a,b,sizeof(a))
    using namespace std;
    typedef unsigned long long ull;
    typedef long long ll;
    const int maxn=1e3;
    const int branch=26;
    const int inf=0x3f3f3f3f;
    const int MOD=1e6+7;
    int dp[maxn+10][maxn+10];
    int book[maxn+10][maxn+10];
    int dfs(int i,int j);
    void init()
    {
        mset(dp,0);
        mset(book,0);
        for(int i=0; i<=maxn; ++i)
            book[i][0]=1;//i  0 状态已经计算过了  是必输状态
        for(int i=1; i<=maxn; ++i)
            for(int j=1; j<=i; ++j)
            {
                dp[i][j]=1;//必胜状态
                book[i][j]=1;
            }
    }
    int dfs(int i,int j)//计算i j状态是必胜还是必输状态 ,此人面对的状态是   可以取i个, 还剩j个的状态
    {
        /*
        1.寻找该状态下 有没有必输状态
        */
        if(book[i][j])
            return dp[i][j];
        /* 此时  i>=1   j>=1  i<j*/
        for(int p=1; p<=i; ++p) //取q 个
        {
            if(!dfs(2*p,j-p))
            {
                book[i][j]=1;
                return dp[i][j]=1;
            }
        }
        book[i][j]=1;
        return dp[i][j]=0;
    }
    int main()
    {
        int n;
        init();
        while(~scanf("%d",&n))
        {
            if(dfs(max(1,n-1),n))
                printf("Small
    ");
            else
                printf("Big
    ");
        }
    //    freopen("../text.txt","w",stdout);
    //    for(int i=1; i<=1000; ++i)
    //    {
    //        if(!dfs(max(1,i-1),i))
    //            printf("%d
    ",i);
    //    }
    //    return 0;
    }
    
    
    

    另外遍历之后发现先手输的状态只有(后者胜,输出"Big")

    2
    3
    5
    8
    13
    21
    34
    55
    89
    144
    233
    377

  • 相关阅读:
    [LeetCode]题解(python):007-Reverse Integer
    [LeetCode]题解(python):006-ZigZag Conversion
    [LeetCode]题解:005-Longest Palindromic Substring优化
    [LeetCode]题解(python):005-Longest Palindromic Substring
    [LeetCode]题解(python):003-Longest Substring Without Repeating Characters
    [LeetCode]题解(python):002-Add Two Numbers
    [LeetCode]题解(python):001-Two-Sum
    【BZOJ1005】【HNOI2008】明明的烦恼
    BZOJ平推计划
    【BZOJ1004】【HNOI20008】cards
  • 原文地址:https://www.cnblogs.com/dchnzlh/p/10427275.html
Copyright © 2011-2022 走看看