约瑟夫环

原创 2013年12月03日 00:15:06

杀人游戏

Problem Description

不知道你是否玩过杀人游戏,这里的杀人游戏可没有法官,警察之类的人,只有土匪,现在已知有N个土匪站在一排,每个土匪都有一个编号,从1到N,每次杀人时给定一个K值,从还活着的土匪中,编号从小到大的找到K个人,然后杀掉,继续往下,直到找遍,然后继续从剩下的土匪中,编号从小到大找到第K个活着的土匪,然后杀掉。比如,现在有10个土匪,K为3,第一次杀掉3,6,9号的土匪,第二次杀掉4,8号土匪,第三次杀掉5号土匪,第四次杀掉7号土匪,第五次杀掉10号土匪,我们看到10号土匪是最后一个被杀掉的(从1到K-1的土匪运气好,不会被杀!)。现在给定你一个N和一个K,问你最后一个被杀掉的土匪的编号是多少。
Input
第一行有一个T(T<=10000),接下来有T组数据,每组中包含一个N(N<2^31)和一个K(3<=K<=100&&K<N)。 
Output
对于每组数据,输出最后被杀的土匪的编号。
Sample Input
1 10 3
Sample Output
10

思路:
这是典型的约瑟环问题,具体可以参见维基百科:点击打开链接。如果我们需要求各个土匪被杀的顺序,那么可以用两个数组去模拟这个过程,其中一个数组保存被杀的土匪序列,另外一个数组保存还未被杀死的土匪数目。
一直循环直到土匪被杀光程序就可以退出。但是,如果我们仅仅需要求最后生还的土匪在一开始时的下标,而需要用两个数组来维护信息,当数组十分大的时候,显然很不经济并且时间复杂度十分高。所以,我们有另外一种思路。
假设F(n,k)表示n个人,轮子为k时的最后生还者索引,讨论第一第二轮,试图找出转移式。第一轮的生还者下标为F(n,k),那么经过第二轮,有n/k个土匪将会被杀害,第二轮的生还者的下标是F(n-n/k,k),如何将F(n,k)与F(n-n/k,k)联系起来呢?两个下标相隔多远?关键是找两个下标之间有多少个土匪被杀掉?答案是个。
可以参照下面的图示,

#include<iostream>
using namespace std;

int KillGame(int n,int k) //n人,每k人杀一个,生还者是第KillGame(n,k)个
{
	if( n == k)
		return n;
	int alive = KillGame(n-n/k,k);
	return (alive-1)/(k-1) + alive;//杀掉一轮后,生还者是第KillGame(n-n/k,k)个
									//,则有F(n,k)=F(n-n/k,k)-1/k-1 +F(n-n/k,k)
}
int main()
{
	int T,man,k;
	cin >> T;
	while(T--)
	{
		cin >> man >> k;
		cout << KillGame(man,k) << endl;
	}
	return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

约瑟夫环数据结构

  • 2017年11月17日 23:06
  • 1KB
  • 下载

数据结构实验报告 约瑟夫环

  • 2017年11月10日 07:23
  • 204KB
  • 下载

详细阐述约瑟夫环问题(报数出队问题)

约瑟夫环问题(Josephus)       用户输入M,N值,从1至N开始顺序循环数数,每数到M输出该数值,直至全部输出。写出C程序。(约瑟夫环问题 Josephus) 直接上代...

约瑟夫环问题

  • 2016年07月05日 01:41
  • 771B
  • 下载

数据结构——制作约瑟夫环

  • 2015年05月17日 17:49
  • 47KB
  • 下载

约瑟夫环问题(顺序表)——C++实现

#include #include #define MAXSIZE 100//人数上限 using namespace std; typedef int DataType; typedef stru...

java simith数和约瑟夫环问题代码

  • 2014年09月23日 18:23
  • 61KB
  • 下载

约瑟夫环问题

  • 2016年05月09日 23:53
  • 54KB
  • 下载

约瑟夫环O(N)和O(M*N)算法详解

约瑟夫环 O(n),O(n*m)算法。递推,动态规划。数组,循环链表。

约瑟夫环源代码

  • 2015年11月14日 21:44
  • 1KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:约瑟夫环
举报原因:
原因补充:

(最多只允许输入30个字)