hdu5643, 递归求解约瑟夫环问题
King's Game
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 832 Accepted Submission(s): 460
The first round, the first person with label 1 counts off, and the man who report number 1 is out.
The second round, the next person of the person who is out in the last round counts off, and the man who report number 2 is out.
The third round, the next person of the person who is out in the last round counts off, and the person who report number 3 is out.
The N - 1 round, the next person of the person who is out in the last round counts off, and the person who report number n−1 is out.
And the last man is survivor. Do you know the label of the survivor?
For each test case, there are only one line, containing one integer n, representing the number of players.
Sample Output
解题思路:
1、当不考虑时间开销的情况下可以用循环链表结构模拟游戏的进行过程, 建立N个节点的链表并初始化,每个节点中记录其一开始的序号,循环N-1次,每次找出要删除的节点并删除,最后剩下的节点中的值输出;
2、为了节省时间,采用效率比较高的递归算法,分析如下:
以下重新编号均是从删除的人员的后一位开始
第1轮中删除该轮中第1位人员,剩下的人员从1开始重新编号直到N-1作为第2轮的编号;
第2轮中删除该轮中编号为2的人员,剩下的人员从1开始重新编号直到N-2作为第3轮的编号;
第3轮中删除该轮中编号为3的人员,剩下的人员从1开始重新编号直到N-3作为第4轮的编号;
········
第 i - 1 轮中编号为 t1 = (i - 1) % ( N - i + 2),由于编号是从1 ~ N- i + 2,不存在编号为0的人员所以当算出来的t1= 0时,将(N - i + 2)赋值给t1,将该轮中编号为t1的人员删除,剩下人员编号从1开始编号直到N - i + 1作为第i轮的编号;
第 i 轮中编号为 t1 = i % ( N - i + 1),由于编号是从1 ~ N- i + 1,不存在编号为0的人员所以当算出来的t1= 0时,将(N - i + 1)赋值给t1,将该轮中编号为t1的人员删除,剩下人员编号从1开始编号直到N-i作为第i + 1轮的编号;
第 i + 1轮中编号为 t1 = (i + 1) % ( N - i ),由于编号是从1 ~ N- i + ,不存在编号为0的人员所以当算出来的t1= 0时,将(N - i )赋值给t1,将该轮中编号为t1的人员删除,剩下人员编号从1开始编号直到N - i - 1作为第i +2轮的编号;
·········
第N轮中编号为t1 = N % (N - N + 1),由于t1 = 0,将(N- N + 1)赋值给t1
现我们倒着推,第1次推理,最后存活的人员在第N轮中的编号为1,F(1)= 1
第2次推理,最后存活的人员在第N - 1轮中的编号的计算 = (第N-1轮被淘汰人员的编号+ 在第N轮被淘汰人员在第N轮的编号) % i
直到第N次推理所得的F(N)即为最后淘汰者在第一轮中的编号
#include<iostream> using namespace std; int main() { int T; cin >> T; while(T--) { int N; cin >> N; int f = 1; for(int i = 2; i <= N; i++) { int t1 = (N - i + 1) % i; if(t1 == 0) t1 = i; f = (f + t1) % i; if(f == 0) f = i; } cout << f << endl; } }
不考虑时间复杂度的情况下,该代码更好理解 #include<iostream> #include<stdlib.h> using namespace std; typedef struct LinkNode { int label; LinkNode *next; }LinkNode; int main() { int T; cin >> T;//输入例子数目 while(T--) { int N; cin>> N;//输入一共有几个人 LinkNode *p, *q, *head; for(int i = 1; i <= N; i++) {//创建链表 if(i == 1) { head = (LinkNode *) malloc(sizeof(LinkNode)); p = q = head; p->label = 1; p->next = NULL; } else { q = (LinkNode *) malloc(sizeof(LinkNode)); q->label = i; q->next = NULL; p->next = q; p = q; if(i == N) { p->next = head; } } } for(int round = 1; round < N; round++) {//模拟淘汰游戏进行 for(int i = 0; i < round; ) { p = q; q = q->next ; i++; if(i == round) { p->next = q->next ; free(q); q = p; } } } cout << q->label << endl; } }
类似的可以参考http://blog.csdn.net/yanweibujian/article/details/50876631