约瑟夫双向生死游戏
[问题描述]:
约瑟夫双向生死游戏是在约瑟夫生者死者游戏的基础上,正向计数后反向计数,然后再正向计数。
具体描述如下: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(" 正向: "); LinkList *p = head; int num = 0; while(p->next){ printf("%d ",p->data); p = p->next; num++; if(num >= n) break; } num = 0; printf(" 反向: "); p = head; while(p->pri){ printf("%d ",p->pri->data); p = p->pri; num++; if(num >= n) break; } printf(" "); } 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("双向链表的构建: "); print(p,all); printf(" "); // 杀人 int flag = 1; int re = all / 2; q = p; printf(" 被踢下船的人所在位置: "); while(all > re){ if(flag == 1) q = kill_m(q,m); else q = kill_k(q,k); //printf(" q->data:%d ",q->data); flag *= -1; all--; } return 0; }