約瑟夫問題——鏈表實現

據說著名猶太歷史學家 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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章