要是你怎么制定游戏规则?
现在有前面15个好人和后面15个坏人,他们围成一圈。现在从第一个好人开始,数到第n个人就拉出去枪毙,继续从被枪毙的那个人下一个人开始数到第n个人,拉出去枪毙,如此直至所有坏人被枪毙。
要求:好人不能被枪毙,坏人枪毙完游戏结束。
约瑟夫问题的来源
据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从。首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。接着,再越过k-1个人,并杀掉第k个人。这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。问题是,给定了和,一开始要站在什么地方才能避免被处决?Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
在网上看到一些人些的算法,有很多人用到了数组和容器,今天思考了半天发现了一个不需要任何数组和容器的算法,极大地降低了算法的时间复杂度,分享出来以供大家参考。
解题思路
阅读题目主干,前K个好人,后K个坏人,由于要枪毙掉所有的坏人,所以这个开始的间隔数应该是大于K的。
我们可以从数字来判断好人还是坏人,1至K表示好人,大于K的数字表示坏人。
一共2K个人,开始游戏,数到坏人,拉出去枪毙,人数变为2K - 1,游戏继续,又数到坏人,依此进行知道所有坏人被枪毙,即人数变为K,结束游戏。
游戏过程中一旦被数到的人是好人,则游戏结束。
以间隔数m = K + 1开始游戏。
因为是从第一个好人开始数的,也就是从数字1开始,数到第K + 1个人,判断是坏人,此时还有2K - 1个人,被枪毙的人后面的坏人顺序号全部前移一位。
继续数,从K + 1开始,数K + 1个人,这个人的序列号是
((K + 1) + (K + 1) - 1) % (2 * k - 1) = 2
第二个人是好人,不能被枪毙,游戏结束,说明间隔K + 1不满足要求。
我们继续用K + 1进行上述游戏,知道找到合适的m使得所有坏人被枪毙。
完整的算法如下
上图右侧算法结果解释
当好人数是3时,以5为间隔,可以干掉所有坏人。
当好人数为15时,以25779600为间隔,可以干掉所有坏人。
网友评论