數據結構設計——約瑟夫雙向生死游戲


約瑟夫雙向生死游戲

[問題描述]:

約瑟夫雙向生死游戲是在約瑟夫生者死者游戲的基礎上,正向計數后反向計數,然后再正向計數。

具體描述如下:30個旅客同乘一條船,因為嚴重超載,加上風高浪大,危險萬分;因此船長告訴乘客,只有將全船一半的旅客投入海中,其余人才能幸免遇難。無奈,大家只得同意這種辦法,並議定30個人圍成一圈,由第一個人開始,順時針依次報數,數到第9人,便把他投入大海中,然后從他的下一個人數起,逆時針數到第5人,將他投入大海,然后從他逆時針的下一個人數起,順時針數到第9人,再將他投入大海,如此循環,直到剩下15個乘客為止。問哪些位置是將被扔下大海的位置。

 

[設計思路]:

本游戲的數學建模如下:假設n個旅客排成一個環形,依次順序編號12,…,n。從某個指定的第1號開始,沿環計數,數到第m個人就讓其出列,然后從第m+1個人反向計數到m-k+1個人,讓其出列,然后從m-k個人開始重新正向沿環計數,再數m個人后讓其出列,然后再反向數k 個人后讓其出列。這個過程一直進行到剩下q個旅客為止。 也就是一個雙向循環鏈表,分別進行正向移動和反向移動,出列相應位置的人

實現:

(1) 輸入旅客的個數,也就是n的值;

(2)正向離開旅客的間隔數,也就是m的值;

(3) 反向離開旅客的間隔數,也就是k的值;

(4) 輸出出列的人所在的位置

 

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

typedef struct LinkList{
    int data;
    struct LinkList *pri;
    struct LinkList *next;
}LinkList;

//尾插入法建立鏈表   鏈表的頭結點head作為返回值
LinkList  *create_LinkListWEI(int n)
{
    LinkList *head, *p, *q;
    head = p =(LinkList*)malloc(sizeof(LinkList));
    p->pri = NULL;
    int i = 2;// 位置
    p->data = 1;
    n--;
    while(n--){
        q = (LinkList  *)malloc(sizeof(LinkList));
        q->data = i;
        q->next = NULL;
        p->next = q;
        q->pri = p;
        p = q;
        i++;
    }
    q->next = head;
    head->pri = q;
    return head;
}

void print(LinkList *head,int n){
    printf("\n正向:\n");
    LinkList *p = head;
    int num = 0;
    while(p->next){
        printf("%d ",p->data);
        p = p->next;
        num++;
        if(num >= n)
            break;
    }
    num = 0;
    printf("\n反向:\n");
    p = head;
    while(p->pri){
        printf("%d ",p->pri->data);
        p = p->pri;
        num++;
        if(num >= n)
            break;
    }
    printf("\n");
}

LinkList  *kill_m(LinkList *head,int m){
    LinkList *p = head;
    LinkList *q;
    int time = 1;
    while(p->next){
        q = p->next;
        if(time == m){
            printf("%d ",p->data);
            //刪除鏈表結點 p
            p->pri->next = q;
            q->pri = p->pri;
            return q;
        }
        p = p->next;
        time++;
    }

}

LinkList  *kill_k(LinkList *head,int k){
    LinkList *p = head;
    LinkList *q;
    int time = 1;
    while(p->pri){
        q = p->pri;
        if(time == k){
            printf("%d ",p->data);
            //刪除鏈表結點 p
            q->next = p->next;
            p->next->pri = q;
            return q;
        }
        p = p->pri;
        time++;
    }
}

int main(){
    int all,m,k;
    /*
    m 正向    k 反向
    */
    scanf("%d %d %d",&all,&m,&k);
    LinkList *p,*q;
    p = create_LinkListWEI(all);
    printf("雙向鏈表的構建:\n");
    print(p,all);
    printf("\n");
    // 殺人
    int flag = 1;
    int re = all / 2;
    q = p;
    printf("\n被踢下船的人所在位置:\n");
    while(all > re){
        if(flag == 1)
            q = kill_m(q,m);
        else
            q = kill_k(q,k);
        //printf("\nq->data:%d\n",q->data);
        flag *= -1;
        all--;
    }
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM