zoukankan      html  css  js  c++  java
  • HDU-4371-Alice and Bob

    题目链接

    http://acm.hdu.edu.cn/showproblem.php?pid=4371

    这题在比赛的时候看错了题意,卡了很久都没做出来,也没有再回头仔细去看题,所以没做出来,之后再看别人的博客才知道,题意弄错了。

    英语一定要给我多记单词,多去翻译文章句子。

    题意:题意:Alice 和 Bob 轮流写数字,假设第 i 次的数字是 S(i) ,那么第 i+1 次的数字 S(i+1)= S(i)+d(k)或 S(i)-d(k),

    条件是 S(i+1)<= n && S(i-1)<S(i+1)。不过题意弄懂了,这个题也不好做。只能引用他人的思路了

    结论:在所有的d中,选择最小的d,这里记作dmin,Alice和Bob每次都选择+dmin(写下的数是在原来的那个数上加上dmin),按照这样的策略最后的结果就是全局的结果。 

    可以这样考虑正确性,不妨假设按照以上策略是Alice获胜,那么Alice并不会主动改变策略;假设Bob在某一步突然改变策略,即没有选择+dmin,那么就必然选择了某个+d(不会是-d,因为这样肯定不合法),且d > dmin,那么下一步Alice就可以选择-dmin了,再下一步,Bob就只能选择某个+d,且d > dmin,Alice则可以一如既往的选择-dmin,如此循环,无论每次Bob做什么样的决策,Alice都可以选择-dmin,所以肯定是Bob最先没有选择,同样是Alice获胜。这样就证明了开头的结论。  

    分析:杂一看真的不好确定必输或必赢状态。那么直接想最后一步,什么时候就结束呢?s(i)+min > n 时就输了;那么s(i-1)又是什么情况呢?s(i-1) 可以选择一个 d(d >min) 或 min 这两种情况,如果选择了 min,那么下一步一定也要向上加,如果选择了是 d 那么有两种情况种是向下面减,和向上面加。于是可以发现先手如果选择了 min 那么后手只能向上加,如果先手选择了 d ,那么后手就可以减去 min ,这样可以保证自己永远有数可以写直到自己赢了。

    代码

    #include<stdio.h>
    int main(void)
    {
    int t,n,m,i,j;
    int s;
    int d[111];
    int min;
    scanf("%d",&t);
    for(i=1;i<=t;i++)
    {
    min=999999999;
    scanf("%d%d",&n,&m);
    for(j=1;j<=m;j++)
    {
    scanf("%d",d+i);
    if(min>d[i])
    min=d[i];
    }
    s=n/min;//Alice先取
    if(s%2==0)//如果s为偶,那么最后是Bob取到n,或少于n,但与n相差不超过min。
    {//所以Alice再取的话,就会 > n 成立。
    printf("Case #%d: Alice ",i);
    }
    else
    {
    printf("Case #%d: Bob ",i);
    }
    }
    return 0;
    }

  • 相关阅读:
    49. 字母异位词分组
    73. 矩阵置零
    Razor语法问题(foreach里面嵌套if)
    多线程问题
    Get json formatted string from web by sending HttpWebRequest and then deserialize it to get needed data
    How to execute tons of tasks parallelly with TPL method?
    How to sort the dictionary by the value field
    How to customize the console applicaton
    What is the difference for delete/truncate/drop
    How to call C/C++ sytle function from C# solution?
  • 原文地址:https://www.cnblogs.com/liudehao/p/3959694.html
Copyright © 2011-2022 走看看