約瑟夫問題——連結串列實現
阿新 • • 發佈:2019-01-10
據說著名猶太曆史學家 Josephus有過以下的故事:在羅馬人佔領喬塔帕特後,39 個猶太人與Josephus及他的朋友躲到一個洞中,39個猶太人決定寧願死也不要被敵人抓到,於是決定了一個自殺方式,41個人排成一個圓圈,由第1個人開始報數,每報數到第3人該人就必須自殺,然後再由下一個重新報數,直到所有人都自殺身亡為止。然而Josephus 和他的朋友並不想遵從。首先從一個人開始,越過k-2個人(因為第一個人已經被越過),並殺掉第k個人。接著,再越過k-1個人,並殺掉第k個人。這個過程沿著圓圈一直進行,直到最終只剩下一個人留下,這個人就可以繼續活著。問題是,給定了和,一開始要站在什麼地方才能避免被處決?Josephus要他的朋友先假裝遵從,他將朋友與自己安排在第16個與第31個位置,於是逃過了這場死亡遊戲。
17世紀的法國數學家加斯帕在《數目的遊戲問題》中講了這樣一個故事:15個教徒和15 個非教徒在深海上遇險,必須將一半的人投入海中,其餘的人才能倖免於難,於是想了一個辦法:30個人圍成一圓圈,從第一個人開始依次報數,每數到第九個人就將他扔入大海,如此迴圈進行直到僅餘15個人為止。問怎樣排法,才能使每次投入大海的都是非教徒。
*問題分析與演算法設計
約瑟夫問題並不難,但求解的方法很多;題目的變化形式也很多。這裡給出一種實現方法。
#include <stdio.h> #include <stdlib.h> typedef struct people{ int num; struct people *front; struct people *next; }Node; void del(Node *p){ p->front->next=p->next; printf("%d ",p->num); free(p); } int main() { int n,i,m; scanf("%d %d",&n,&m); Node *p1,*p2,*head; p1=(Node *)malloc(sizeof(Node)); p1->num=1; head=p1; p2=p1; for(i=2;i<=n;i++){ p1=(Node *)malloc(sizeof(Node)); p1->num=i; p2->next=p1; p1->front=p2; p2=p1; } p2->next=head; head->front=p2; Node *p=head,*p3; while(n-->1){ for(i=0;i<m;i++){ p=p->next; } p3=p; p=p->next; del(p3); } printf("\n%d\n",p->num); return 0; }