zoukankan      html  css  js  c++  java
  • 剑指Offer——孩子们的游戏(圆圈中最后剩下的数)

    题目描述:

    每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0...m-1报数....这样下去....直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!^_^)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)


    分析:

     这是约瑟夫环(约瑟夫问题)。

    问题是从n个人编号分别为0...n-1,取第m个,
    则第m个人编号为m-1的淘汰,剩下的编号为0,1,2,3...m-2,m,m+1,m+2,...
    此时因为从刚刚淘汰那个人的下一个开始数起,因此重新编号
    把m号设置为0,则
    m 0
    m+1 1
    ...
    0 n-m
    1 n-m+1

    假设已经求得了n-1个人情况下的最终胜利者保存在f[n-1]中,
    则毫无疑问,该胜利者还原到原来的真正编号即为 (f[n-1]+m)%n。
    (因为第二轮重新编号的时候,相当于把每个人的编号都减了m,因此重新+m即可恢复到原来编号)。
    由此,我们可以想象,当最终只剩下一个人的时候,该人即为胜利者,此时重新编号,因为只有一个人,
    所以此时f[1]=0。
    这样f[2]=(f[1]+m)%2,这样就可以求出最终胜利者在2个人的时候的情况下的编号,
    由递推公式f[n]=(f[n-1]+m)%n,可递推到最初编号序列中该胜利者的编号。


    代码:

    1 class Solution {
    2 public:
    3     int LastRemaining_Solution(int n, int m) {
    4         if(n == 0 || m == 0) return -1;
    5         int res = 0;
    6         for(int i = 2; i <= n; i++) res = (res + m) % i;
    7         return res;
    8     }
    9 };
  • 相关阅读:
    poj1661【DP,左右两端dp】
    hdoj1074【A的无比爆炸】
    hdoj1024【DP.最 大 m 字 段 和】(写完我都怕。。。不忍直视。。)
    qq教xixi写模拟加法【非常爆炸】
    错排公式
    POJ3616【基础DP】
    hdoj1257【疑问】(贪心)
    【弱的C艹之路。。未完待续】
    hdoj1728【搜索的两种写法】
    hdoj1001【智障了。。。】
  • 原文地址:https://www.cnblogs.com/jacen789/p/7747749.html
Copyright © 2011-2022 走看看