POJ1012Joseph解题报告
2015-10-22 21:19
232 查看
Joseph
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 50604 Accepted: 19241
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个圈的大小,所以等效于对圈的大小取模。
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 50604 Accepted: 19241
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> #include<cstdio> using namespace std; int main(void) { freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); int Joseph[14]={0}; //打表,保存各个k值对应的m值,用于剪枝 int k; while(cin>>k&&k){ if(Joseph[k]){ cout<<Joseph[k]<<endl; continue; } int n=2*k; int ans[30]={0}; int m=k+1;//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<<endl<<m<<endl; } return 0; }
相关文章推荐
- 深入理解约瑟夫环的数学优化方法
- 批处理解约瑟夫环应用题代码
- java 实现约瑟夫环的实例代码
- php解决约瑟夫环示例
- 详解约瑟夫环问题及其相关的C语言算法实现
- C++循环链表之约瑟夫环的实现方法
- 约瑟夫环问题(数组法)c语言实现
- python超简单解决约瑟夫环问题
- 【OJ日志】超级约瑟夫
- 初学ACM - 组合数学基础题目PKU 1833
- 约瑟夫自杀环
- POJ ACM 1001
- POJ ACM 1002
- POJ 2635 The Embarrassed Cryptographe
- POJ 3292 Semi-prime H-numbers
- POJ 2773 HAPPY 2006
- POJ 3090 Visible Lattice Points
- POJ-2409-Let it Bead&&NYOJ-280-LK的项链
- POJ-1695-Magazine Delivery-dp
- POJ1523 SPF dfs