导航

编程题目记录131221:n人隔m一杀

Posted on 2013-12-22 10:21  生存在夹缝中  阅读(211)  评论(0)    收藏  举报

题目:

  n个数字(0,1,…,n-1)形成一个圆圈,从数字0开始,每次从这个圆圈中删除第m个数字(第一个为当前数字本身,第二个为当前数字的下一个数字)。当一个数字删除后,从被删除数字的下一个继续删除第m个数字。求出在这个圆圈中剩下的最后一个数字。

 

思路:

  想了好多除了链表模拟以外的方法,但是都不如这个简单省事,所以最后干脆还是用链表模拟了。(最简方案附在最后)

 

方案:

  用环形双向链表模拟整个过程,并计算步数,选择两个方向中最短的那个方向行动

 

代码:

 1 //题目5:n个数字(0,1,…,n-1)形成一个圆圈,从数字0开始,每次从这个圆圈中删除第m个数字(第一个为当前数字本身,
 2 //第二个为当前数字的下一个数字)。当一个数字删除后,从被删除数字的下一个继续删除第m个数字。求出在这个圆圈中
 3 //剩下的最后一个数字。
 4 
 5 //思路:想了半天,没有办法解决数组的隔位删除,只能用链表模拟
 6 //利用机器暴力解决东西而不是找到公式,真是人脑的失败
 7 //这东西好像叫什么马尔科夫链吧?要不就是马尔代夫群岛,嗯…… 
 8 
 9 #include <stdio.h>
10 #include <stdlib.h>
11 
12 typedef struct LinkNode
13 {
14     int number;
15     struct LinkNode *next,*prev;
16 }LinkNode;
17 
18 LinkNode *PeopleInit(int N);
19 int GoKillThem(LinkNode *round,int M,int N);
20 
21 int main()
22 {
23     int N,M;
24     printf("Please enter the N:");
25     scanf("%d",&N);
26     printf("Please enter the M:");
27     scanf("%d",&M);
28     
29     LinkNode *round=PeopleInit(N);
30     printf("The result is:%d\n",GoKillThem(round,M,N));
31     return 0;
32 }
33 
34 LinkNode *PeopleInit(int N)
35 {
36     int i;
37     LinkNode *round=(LinkNode *)malloc(sizeof(LinkNode));
38     round->number=0;
39     LinkNode *current=round;
40     for(i=1;i<=N-1;++i)
41     {
42         current->next=(LinkNode *)malloc(sizeof(LinkNode));
43         current->next->number=i;
44         current->next->prev=current;
45         current=current->next;
46     }
47     current->next=round;
48     round->prev=current;
49     return round;
50 }
51 
52 int GoKillThem(LinkNode *round,int M,int N)
53 {
54     int i,step,j,head_mark=1;//人数迭代器、步数、步数迭代器、方向标志(-1逆1正) 
55     LinkNode *current=round;
56     for(i=0;i<=N-2;++i)//杀n-1个人的循环 
57     {
58         step=(M-1)%(N-i);//圈内走几步 
59         if(step>(N-i-step))//逆着走更快
60         {
61             step=N-i-step;
62             head_mark=-1;
63         }
64         else
65             head_mark=1;
66         for(j=1;j<=step;++j)
67         {
68             if(head_mark==1)//正着走 
69                 current=current->next;
70             else//逆着走 
71                 current=current->prev;
72         }
73         LinkNode *new_current=current->next,*new_prev=current->prev;
74         new_prev->next=new_current;
75         new_current->prev=new_prev;
76         printf("I kill %d hahaha!\n",step,head_mark,current->number);
77         free(current);//干掉这个家伙
78         current=new_current; 
79     }
80     return current->number;
81 }

 

附加:

  这个题其实是有公式的,公式代码以及来源在这里:http://blog.csdn.net/hjj414/article/details/17471821