算法12---约瑟夫环问题
1 首先我们来解决一个约瑟夫环的问题,再慢慢的深入。
问题描述:
罗马人攻占了桥塔帕克,41个人躲在一个山洞中,逃过了这场浩劫。这41人中,包括历史学家约瑟夫和他的一个朋友。剩余的39人为了表示不想屈服罗马人,决定集体自杀。大家想到了一个自杀方案,这41个人围城一个圆圈,由第一个人开始顺时针报数,每报数为3的人就立刻自杀。然后再由下一个人重新开始报数,仍然是每报数为3的人自杀,。。。。,直到所有的人都自杀身亡;
约瑟夫和他的朋友不想自杀,于是约瑟夫想到了一个计策,他们两个同样的参与到自杀方案中,但是最后却躲过了自杀,请问,他是怎么做到的?
1 #include <String.h> 2 #include <stdio.h> 3 #include <malloc.h> 4 5 6 #define Num 41 7 #define killman 3 8 9 void josephus(int alive) 10 { 11 int man[Num]={0}; 12 int count=1; 13 int i=0; 14 int pos=-1; 15 while(count<=Num) 16 { 17 do 18 { 19 pos=(pos+1)%Num;//环处理 20 if (man[pos]==0) 21 { 22 i++; 23 } 24 if (i==killman) 25 { 26 i=0; 27 break; 28 } 29 }while(1); 30 man[pos]=count; 31 printf("the %2d people die! the number of josephus is %2d\n",pos+1,man[pos]); 32 33 count++; 34 } 35 printf("the %d man who want to live should be in the number of :\n",alive ); 36 alive=Num-alive; 37 for (int i = 0; i < Num; i++) 38 { 39 if (man[i]>alive) 40 { 41 printf("init number:%d.josephus number:%d\n",i+1,man[i]); 42 } 43 } 44 printf("\n"); 45 } 46 47 48 int main() 49 { 50 int alive; 51 printf("the solve of josephus!\n"); 52 printf("the number fo people want to live:"); 53 scanf("%d",&alive); 54 josephus(alive); 55 return 0; 56 }
2 我们就上面的问题引出josephus排序问题;
就是对任意输入的人数,决定自杀的个数,输出自杀的顺序;
1 #include <String.h> 2 #include <stdio.h> 3 #include <malloc.h> 4 5 6 #define Num 41 7 #define killman 4 8 9 void josephus_sort() 10 { 11 int man[Num]={0}; 12 int count=1; 13 int i=0; 14 int pos=-1; 15 while(count<=Num) 16 { 17 do 18 { 19 pos=(pos+1)%Num;//环处理 20 if (man[pos]==0) 21 { 22 i++; 23 } 24 if (i==killman) 25 { 26 i=0; 27 break; 28 } 29 }while(1); 30 man[pos]=count; 31 printf("the %2d people die! the number of josephus is %2d\n",pos+1,man[pos]); 32 33 count++; 34 } 35 } 36 37 38 39 int main(void) 40 { 41 42 printf("the solve of josephus sort!\n"); 43 44 josephus_sort(); 45 return 0; 46 }
3 现在接着上面的问题,升级一下:n个人坐成一个圈,现在每个人都拿一个随机写有数字的字条,游戏开始,任选一个数字m。从第一个人开始进行,按照编号重新开始报数,报道m的人出列,并且将其手中的数字作为新的出列数字。然后从下一个人开始重新从1开始报数,如此循环下去,问最后剩下来哪个人?
1 /* 2 由于在这里下一个决定出列的数字随机生成的,而且总的个数是可以自己定义的; 3 在这里我们采用链表的方式来解答。 4 */ 5 6 7 #include <string.h> 8 #include <stdio.h> 9 #include <malloc.h> 10 #include <time.h> 11 12 #define random_len 10 13 14 typedef struct node 15 { 16 int number; //游戏者编号 17 int psw; //出列数字 18 struct node *next; //指针域,指向下一个节点 19 }Lnode,*linklist; 20 21 22 23 void circleFun(linklist *list,int m) 24 { 25 linklist p,q; 26 q=p=*list; 27 while(q->next!=p) 28 { 29 q=q->next; 30 } 31 printf("the gamer out the list in this order!\n"); 32 while(p->next!=p) 33 { 34 for (int i = 0; i < m-1; i++) 35 { 36 q=p; 37 p=p->next; 38 } 39 q->next=p->next; 40 printf("the %d people pop,the number in his hand is %d\n",p->number,p->psw ); 41 m=p->psw; 42 free(p); 43 p=q->next; 44 } 45 46 printf("the last one is %d,the number in his hand is %d \n",p->number,p->psw ); 47 } 48 49 void insertlist(linklist *list,linklist q,int number ,int psw) 50 { 51 linklist p; 52 p=(linklist)malloc(sizeof(Lnode)); 53 54 p->number=number; 55 p->psw=psw; 56 if (!*list) 57 { 58 *list=p; 59 p->next=NULL; 60 } 61 else 62 { 63 p->next=q->next; 64 q->next=p; 65 } 66 } 67 68 69 int main() 70 { 71 linklist list1=NULL,q=NULL,list; 72 int num,m_number; //m_number为第一个决定出列的数字; 73 int e; 74 printf("the solve of complex josephus problem\n"); 75 printf("please input the number of people who join the game:"); 76 scanf("%d",&num); 77 srand(time(NULL)); 78 for (int i = 0; i < num; i++) 79 { 80 e=rand()%10; 81 printf("the number in %d people's hand %d \n",i+1,e); 82 insertlist(&list1,q,i+1,e); 83 if (i==0) 84 { 85 q=list1; 86 } 87 else 88 q=q->next; 89 } 90 q->next=list1; 91 list=list1;//循环链表 92 93 printf("please input the number first input:\n"); 94 scanf("%d",&m_number); 95 circleFun(&list,m_number); 96 printf("\n"); 97 return 0; 98 }