標籤:style blog http color io os ar strong for
問題來曆
據說著名猶太曆史學家 Josephus有過以下的故事:在羅馬人佔領喬塔帕特後,39 個猶太人與Josephus及他的朋友躲到一個洞中,39個猶太人決定寧願死也不要被敵人抓到,於是決定了一個自殺方式,41個人排成一個圓圈,由第1個人開始報數,每報數到第3人該人就必須自殺,然後再由下一個重新報數,直到所有人都自殺身亡為止。然而Josephus 和他的朋友並不想遵從。首先從一個人開始,越過k-2個人(因為第一個人已經被越過),並殺掉第
k個人。接著,再越過k-1個人,並殺掉第
k個人。這個過程沿著圓圈一直進行,直到最終只剩下一個人留下,這個人就可以繼續活著。問題是,給定了和,一開始要站在什麼地方才能避免被處決?Josephus要他的朋友先假裝遵從,他將朋友與自己安排在第16個與第31個位置,於是逃過了這場死亡遊戲。17世紀的法國數學家加斯帕在《數目的遊戲問題》中講了這樣一個故事:15個教徒和15 個非教徒在深海上遇險,必須將一半的人投入海中,其餘的人才能倖免於難,於是想了一個辦法:30個人圍成一圓圈,從第一個人開始依次報數,每數到第九個人就將他扔入大海,如此迴圈進行直到僅餘15個人為止。問怎樣排法,才能使每次投入大海的都是非教徒。
分析1:(1)由於對於每個人只有死和活兩種狀態,因此可以用布朗型數組標記每個人的狀態,可用true表示死,false表示活。(2)開始時每個人都是活的,所以數組初值全部賦為false。(3)類比殺人過程,直到所有人都被殺死為止。C++代碼:
1 #include<iostream> 2 using namespace std; 3 int main() 4 { 5 bool a[101]={0}; 6 intn,m,i,f=0,t=0,s=0; 7 cin>>n>>m; 8 do 9 {10 ++t;//逐個枚舉圈中的所有位置11 if(t>n)12 t=1;//數組類比環狀,最後一個與第一個相連13 if(!a[t])14 s++;//第t個位置上有人則報數15 if(s==m)//當前報的數是m16 {17 s=0;//計數器清零18 cout<<t<<‘‘;//輸出被殺人編號19 a[t]=1;//此處人已死,設定為空白20 f++;//死亡人數+121 }22 }while(f!=n);//直到所有人都被殺死為止23 return 0;24 }
C代碼:
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 typedef struct node 5 { 6 int data; 7 struct node *next; 8 }Node; 9 10 Node *creat(int n)11 {12 Node *p, *head;13 head = (Node *)malloc(sizeof(Node));14 p = head;15 Node *s;16 int i = 0;17 18 if(0 != n)19 {20 while(i <= n)21 {22 s = (Node *)malloc(sizeof(Node));23 s->data = i++;24 p->next = s;25 p = s; 26 }27 s->next = head->next; 28 }29 free(head);30 return s->next;31 }32 33 int main()34 {35 int n = 41, m = 3;36 int i;37 Node *p = creat(n);38 Node *temp;39 40 m %= n;41 42 while(p != p->next)43 {44 for(i = 1; i < m-1; i++)45 {46 p = p->next;47 }48 printf("%d ", p->next->data);49 temp = p->next;50 p->next = temp->next;51 52 free(temp);53 p = p->next;54 }55 printf("%d\n", p->data);56 57 return 0;58 }
基礎演算法1——約瑟夫問題