首页 > 代码库 > 经典算法之约瑟夫问题

经典算法之约瑟夫问题

  1     /************************************************************************************** 
  2     * Function     : 约瑟夫问题 
  3     * Create Date  : 2014/04/20 
  4     * Author       : NTSK13 
  5     * Email        : beijiwei@qq.com 
  6     * Copyright    : 欢迎大家和我一起交流学习,转载请保持源文件的完整性。 
  7                                                   任何单位和个人不经本人允许不得用于商业用途 
  8     * Version      : V0.1                    
  9     ***************************************************************************************                    
 10      
 11     题目: 
 12     约瑟夫问题 
 13      
 14         有n个人围成一圈,顺序排号。从第一个人开始报数(从1到3报数),凡报到3的人退出 
 15         圈子,问最后留下的是原来第几号的那位 
 16     分析: 
 17     //My anser: 
 18      常规解法,模拟数数自杀过程。自杀的人下次数数直接跳过。 
 19     **************************************************************************************/  
 20     #include<stdio.h>  
 21       
 23     #define MY_FUNC  1  
 24     #if MY_FUNC  
 25         
 27     #define N 3//数到3  
 28     #define M 41  
 29     int data[]={0};  
 30       
 32     int remain(int n);  
 33     //the first solution:  
 34     int main()  
 35     {  
 36         int ret=0;  
 39         ret=remain(M);  
 40           
 41         printf("The last remain number is: %d \n",ret);  
 42         fflush(stdout);//修复Eclipse printf()不能显示的小bug  
 45         return 0;  
 46     }  
 47       
 48       
 49     int remain(int n)  
 50     {  
 51         int i=0,j=0,die=0;  
 52         int current=1,k=1;  

 55         for(j=0;j<n;j++)  
 56             data[j]=j+1;  
 57       
 59         while(die<n)  
 60         {  
 61             if(current==N+1)//顺序数数123,123,....  
 62                 current=1;  
 65             if(current==N)//数到3的时候,要移除一个不为0的数,为0 代表人已自杀死去  
 66             {  
 67                 j=i;  
 68                 if(j>n)  
 69                     j=j%n;  
 70                 while(1)//remove a death  
 71                 {  
 72                     if(data[j]!=0)  
 73                     {  
 74                         data[j]=0;  
 75                         printf("第%d个死去的人编号是: %d \n",k++,j+1);  
 76                                 fflush(stdout);  
 77                         die++;  
 78                         break;  
 79                     }  
 80                     else  
 81                     {  
 82                         j++;  
 83                         if(j==n)  
 84                             j=0;  
 85                     }  
 86                 }  
 87                 if(die==n)  
 88                     break;  
 89             }  
 90             else//数数序列号不为3的时候,继续数数,但是要跳过死去的人  
 91             {  
 92                 while(1)//jump death  
 93                 {  
 94                     if(data[i]!=0)  
 95                         break;  
 96                     else  
 97                     {  
 98                         i++;  
 99                         if(i==n)  
100                             i=0;  
101                     }  
102                 }  
103             }  
104       
105       
106             current++;//计数加一  
107             i++;      //  
108             if(i==n)  
109                 i=0;  
110         }  
111       
112         return j+1;  
113     }  
114     #else  
115     /************************************************************************************/  
116       
117       
118     //the second solution:  
119       
120     #include <stdio.h>  
121     #include <stdlib.h>  
122     #define N 41  
123     #define M 3  
124     int main()  
125     {  
126         int man[N]={0};  
127         int count=1;  
128         int i=0,pos=-1;  
129         int alive=0;  
130         while(count<=N)  
131         {  
132             do{  
133                 pos=(pos+1) % N;  //环状处理  
134                 if(man[pos]==0)  
135                     i++;  
136                 if(i==M) //报数3的人  
137                 {  
138                     i=0;  
139                     break;  
140                 }  
141             }while(1);  
142             man[pos]=count;  
143             count++;  
144         }  
145         printf("\n约瑟夫排列(最初位置-约瑟夫环位置):\n");  
146         fflush(stdout);  
147         for(i=0;i<N;i++)  
148         {  
149             printf("%d-%d  ",i+1,man[i]);  
150             fflush(stdout);  
151             if(i!=0 && i%10==0) //每输出10个则换行  
152                 {  
153                     printf("\n");  
154                     fflush(stdout);  
155                 }  
156         }  
157         printf("\n\n请输入准备剩下的人数:\n");  
158         fflush(stdout);  
159         scanf("%d", &alive);  
160         printf("这%d人初始位置应排在以下序号:\n",alive);  
161         fflush(stdout);  
162         alive=N-alive;  
163         for(i=0;i<N;i++)  
164             if(man[i]>alive)  
165             {  
166                 printf("初始序号:%d,约瑟夫环序号:%d\n",i+1,man[i]);  
167                 fflush(stdout);  
168             }  
169         printf("\n");  
170         fflush(stdout);  
171         getch();  
172         return 0;  
173     }  
 
176     #endif