1 /*
2 约瑟环问题其实就是一个循环链表的问题
3 */
4 #include <iostream>
5 #include<ctime>
6 using namespace std;
7
8 //动态规划的思想,有点类似解决主元素问题的思路
9 //巧妙的用0,1数组代替链表节点的删除
10 int sun1(const int N,const int C)
11 {
12 int i=0,j=0,n=N,s=0;
13 int t=0;
14 int *a=new int [N];
15 for (i=0;i<N;i++)
16 {
17 a[i]=1;
18 }
19
20 while(0!=n)
21 {
22 s+=a[j]; //前面的数相加每加够C出列一个数
23 if(C==s)
24 {
25 a[j]=0;
26 s=0; //要清0
27 --n;
28 if(0!=n)
29 cout<<j+1<<"->"; //s[j]实际对应的是第j+1个人
30 else
31 {
32 cout<<j+1<<endl;
33 t=j+1;
34 }
35
36 }
37 //j=(j+1)%N; // 循环队列,这里处理很巧妙
38 j= (j==N-1)?0:j+1;
39 }
40 delete []a;
41 return t;
42
43 }
44 /*
45 递推的方法
46 N=1,winner=0;
47 N=i,winner=(winner(0)+C)%i;
48 winner +=1;
49 */
50 int sun2(const int N, const int C)
51 {
52 int f=0;
53 for(int i=2;i<=N;i++)
54 {
55 f=(f+C)%i;
56 }
57 return f+1;
58 }
59 /*循环链表 */
60 int sun3(const int N,const int C)
61 {
62 struct node
63 {
64 int num;
65 node *next;
66 node(const int i)
67 {
68 num=i;
69 next=NULL;
70 }
71 };
72 //初始化链表
73 node *first=NULL;
74 node *opp=first;
75 for(int i=1;i<=N;i++)
76 {
77 node *t=new node(i);
78 if(first==NULL)
79 first=t;
80 else
81 opp->next=t;
82 opp=t;
83 }
84
85 opp->next=first;
86 int winner=0;
87 opp=first;
88 while(true)
89 {
90 for(int i=2;i<=C-1;i++)// 这里注意找到的是出列的节点的父节点
91 opp=opp->next;
92 node *temp=opp->next;
93 cout<<temp->num;
94 if(opp!=temp)
95 {
96 cout<<"->";
97 //删除节点
98 opp->next=temp->next;
99 opp=opp->next;
100 delete temp;
101 }
102 else
103 {
104 winner=temp->num;
105 cout<<"\n";
106 delete opp;
107 break;
108 }
109 }
110 return winner;
111
112 }
113
114
115
116 int main()
117 {
118 ios::sync_with_stdio(false);
119 int N=0,C=0;
120 cout<<"Please enter the number of people:N=";
121 cin>>N;
122 cout<<"Please enter:C=";
123 cin>>C;
124 cout<<"winner is "<<sun1(N,C)<<endl;
125 clock_t end1=clock();
126 cout<<"winner is "<<sun2(N,C)<<endl;
127 clock_t end2=clock();
128 cout<<(end2-end1)/float(CLOCKS_PER_SEC)<<"seconds"<<endl;
129 cout<<"winner is "<<sun3(N,C)<<endl;
130 return 0;
131 }