C语言单向循环链表解决约瑟夫问题

浏览:
字体:
发布时间:2013-12-23 12:22:23
来源:
据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从。首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。接着,再越过k-1个人,并杀掉第k个人。这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。问题是,给定了和,一开始要站在什么地方才能避免被处决?Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。17世纪的法国数学家加斯帕在《数目的游戏问题》中讲了这样一个故事:15个教徒和15 个非教徒在深海上遇险,必须将一半的人投入海中,其余的人才能幸免于难,于是想了一个办法:30个人围成一圆圈,从第一个人开始依次报数,每数到第九个人就将他扔入大海,如此循环进行直到仅余15个人为止。问怎样排法,才能使每次投入大海的都是非教徒。*问题分析与算法设计约瑟夫问题并不难,但求解的方法很多;题目的变化形式也很多。这里给出一种实现方法。题目中30个人围成一圈,因而启发我们用一个循环的链来表示。可以使用结构数组来构成一个循环链。结构中有两个成员,其一为指向下一个人的指针,以构成环形的链;其二为该人是否被扔下海的标记,为1表示还在船上。从第一个人开始对还未扔下海的人进行计数,每数到9时,将结构中的标记改为0,表示该人已被扔下海了。这样循环计数直到有15个人被扔下海为止。约瑟夫问题是个有名的问题:N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉。例如N=6,M=5,被杀掉的人的序号为5,4,6,2,3。最后剩下1号。假定在圈子里前K个为好人,后K个为坏人,你的任务是确定这样的最少M,使得所有的坏人在第一个好人之前被杀掉。解决方案:
/*************************************************************************	> File Name: josefu.c	> Author: Baniel Gao	> Mail: createchance@163.com 	> Blog: blog.csdn.net/createchance 	> Created Time: Thu 19 Dec 2013 03:08:21 PM CST ************************************************************************/#include #include typedef struct josefu{	int data;	struct josefu *next;} josefu_list;josefu_list *josefu_init(int num);josefu_list *josefu_begin(josefu_list *list, int rule);josefu_list *josefu_node(int num);int josefu_free(josefu_list *list);int main(void){	josefu_list *list;	int num, rule;		puts("Please input number and rules: ");	scanf("%d%d", &num, &rule);	list = josefu_init(num);	list = josefu_begin(list, rule);	josefu_free(list);	return 0;}josefu_list *josefu_init(int num){	int i;	josefu_list *new;	josefu_list *list = josefu_node(1);	for(i = num; i > 1; i--) {		new = josefu_node(i);		new->next = list->next;		list->next = new;	}	return list;}josefu_list *josefu_node(int num){	josefu_list *p = NULL;	p = (josefu_list *)malloc(sizeof(josefu_list));	p->data = num;	p->next = p;	return p;}josefu_list *josefu_begin(josefu_list *list, int rule){	int counter;	josefu_list *tmp = NULL;	for(counter = 1; list->next != list; counter++) {		if(counter == rule - 1) {			tmp = list->next;			list->next = tmp->next;			free(tmp);			counter = 0;			josefu_show(list);		}		list = list->next;	}	return list;}int josefu_show(josefu_list *list){	josefu_list *p = list;	if(list == NULL)		return 0;	do {		printf("%5d",p->data);		p = p->next;	} while(list != p);	putchar('/n');}int josefu_free(josefu_list *list){	free(list);	return 0;}

运行实例:


>更多相关文章
24小时热门资讯
24小时回复排行
资讯 | QQ | 安全 | 编程 | 数据库 | 系统 | 网络 | 考试 | 站长 | 关于东联 | 安全雇佣 | 搞笑视频大全 | 微信学院 | 视频课程 |
关于我们 | 联系我们 | 广告服务 | 免责申明 | 作品发布 | 网站地图 | 官方微博 | 技术培训
Copyright © 2007 - 2024 Vm888.Com. All Rights Reserved
粤公网安备 44060402001498号 粤ICP备19097316号 请遵循相关法律法规
');})();