POJ 1012

Joseph

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 57441   Accepted: 21872

Description

The Joseph's problem is notoriously known. For those who are not familiar with the original problem: from among n people, numbered 1, 2, . . ., n, standing in circle every mth is going to be executed and only the life of the last remaining person will be saved. Joseph was smart enough to choose the position of the last remaining person, thus saving his life to give us the message about the incident. For example when n = 6 and m = 5 then the people will be executed in the order 5, 4, 6, 2, 3 and 1 will be saved. 

Suppose that there are k good guys and k bad guys. In the circle the first k are good guys and the last k bad guys. You have to determine such minimal m that all the bad guys will be executed before the first good guy. 
 

Input

The input file consists of separate lines containing k. The last line in the input file contains 0. You can suppose that 0 < k < 14.

Output

The output file will consist of separate lines containing m corresponding to k in the input file.

Sample Input

3
4
0

Sample Output

5
30

Source

Central Europe 1995

约瑟夫环的变形。关于约瑟夫环,可以看: 
http://blog.csdn.net/dafang_xu/article/details/49335583 
本题中,坏人被清除掉的先后顺序无关紧要,知道下一个除掉的是好人还是坏人就行了。由于好人一直都是k个,每除掉一个坏人,坏人数-1,所以队列的总数每次-1但是好人一直是前k个。 
当一个坏人出圈后,圈内总人数减少一个,但不变的是坏人总是在最后那几个,他们的编号大于K。

递推公式: 
ans[i]=(ans[i-1]+m-1)%(n-i+1); (i>1 , 总人数n=2k 则n-i为第i轮剩余的人数) 
ans[i]; //第i-1轮杀掉一个坏人之后重新编号,ans[i]表示应该杀掉此时编号为ans[i]的人 
处理问题中为了区分好人坏人,我们始终从好人开始编号1,2,3,..k,k+1,….。这样构成一个环。假设k=5,1,2,3,4,5,6,7,8,910,m=6,首先第6个人是坏人,杀掉他后需要对圈进行重新排序1,2,3,4,5,6,7,8,9。 
从杀掉的那个第6个坏人往后再数6个人,他是好人还是坏人?当然要看他在新圈里面是不是前k个人。 
m+6-1=11:1,2,3,4,5,6(杀掉第6个之前是第7个),7(杀掉第6个之前是第8个),8(杀掉第6个之前是第9个),9(杀掉第6个之前是第10个),10(杀掉第6个之前是第11个),11(杀掉第6个之前是第12个)。杀掉第六个后还剩9个人,并没有11个人。于是编号大于9的那部分人就要回到圈的开头开始编号,等效于他们的编号减去圈的大小,当然也可能减去n个圈的大小,所以等效于对圈的大小取模。

#include <iostream>
using namespace std;

int main()
{
 int joseph[14]={0};
 int k;
 while(cin>>k&&k!=0) 
 {
 	if(joseph[k])
 	{
 		cout<<joseph[k]<<endl;
 		continue;
	 }
	 int ans[30]={0};
	 int n=2*k;
	 int m=k+1;
	 for(int i=1;i<=k;i++)
	 {
	 	ans[i]=((ans[i-1]+m-1)%(n-i+1));
	 	if(ans[i]<k)
	 	{
	 		i=0;
	 		m++;
		 }
	 }
	 joseph[k]=m;
	 cout<<m<<endl;
 }
}

猜你喜欢

转载自blog.csdn.net/qq_40421671/article/details/81184780