約瑟夫雙向生死游戲
[問題描述]:
約瑟夫雙向生死游戲是在約瑟夫生者死者游戲的基礎上,正向計數后反向計數,然后再正向計數。
具體描述如下:30個旅客同乘一條船,因為嚴重超載,加上風高浪大,危險萬分;因此船長告訴乘客,只有將全船一半的旅客投入海中,其余人才能幸免遇難。無奈,大家只得同意這種辦法,並議定30個人圍成一圈,由第一個人開始,順時針依次報數,數到第9人,便把他投入大海中,然后從他的下一個人數起,逆時針數到第5人,將他投入大海,然后從他逆時針的下一個人數起,順時針數到第9人,再將他投入大海,如此循環,直到剩下15個乘客為止。問哪些位置是將被扔下大海的位置。
[設計思路]:
本游戲的數學建模如下:假設n個旅客排成一個環形,依次順序編號1,2,…,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; }