约瑟夫环问题

1、项目简介:

约瑟夫生者死者游戏的大意是:30个旅客同乘一条船,因为严重超载,加上风高浪大危险万分;因此船长告诉乘客,只有将全船一半的旅客投入海中,其余人才能幸免于难。无奈,大家只得同意这种方法,并议定30个人围成一圈,由第一个人开始,依次报数,数到第9人,便将他投入大海中,然后从他的下一个人数起,数到第9人,再将他投入大海,如此循环,直到剩下15个乘客为止。问哪些位置是将被扔下大海的位置。

2、项目功能要求:

本游戏的数学建模如下:假如N个旅客排成一个环形,依次顺序编号1, 2, , N。从某个指定的第S号开始。沿环计数,每数到第M个人就让其出列,且从下一个人开始重新计数,继续进行下去。这个过程一直进行到剩下K个旅客为止。

 使用单循环链表来存储旅客的位置信息,然后在for循环内找到死亡旅客的位置,找到该位置后将前一个位置的next指针连接到下一个位置上,相当于删除了该死亡旅客的位置,并将其信息打印出来,之后总人数减一。逐步寻找并删除,直至总人数等于幸存者人数,然后按位置的大小顺序排序后打印出幸存者位置。

#include <iostream>
using namespace std;
#include <cstring>
#include <stdlib.h>
#include <malloc.h>
#include"Stack.h"

/*----玩家结构体----*/
struct Player {
	int pos;               //玩家所处初始位置
	struct Player* Next;  //尾指针
};                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
/*----核心函数----*/
Player* solve(int n, int s, int m, int k) {
	Player* p;                         //临时指针
	Player* Josephus = new Player[n];  //创建约瑟夫循环链表
	int count = 1;                     //计数器
	//约瑟夫环的初始化
	for (int i = 0; i < n; i++) {
		Josephus[i].pos = i + 1;
		if (i != n - 1)
			Josephus[i].Next = &Josephus[i + 1];
		else
			Josephus[i].Next = &Josephus[0];
	}
	//寻找第一个位置,对s = 1进行特殊处理
	s--;
	if (s - 1 >= 0)
		p = &Josephus[s - 1];
	else
		p = &Josephus[n - 1];
	//将死者删除出链表,累加位置,直到达到人数要求
	while (n > k) {
		for (int i = 0; i < m - 1; i++)
			p = p->Next;
		cout << "第" << count << "个死者的位置是:    " << p->Next->pos << endl;
		n--;
		count++;
		p->Next = p->Next->Next;
	}
	//为达到从小到大输出,移动指针
	while (p->pos < p->Next->pos)
		p = p->Next;
	p = p->Next;
	return p;
}
//单循环链表实现
int main()
{//为了让游戏更加具有普适性,定义为:现有N人围成一圈,
 //从第S个人开始依次报数,报M的人出局,再由下一个人
 // 开始报数,如此循环,直到剩下K个人为止。
 //显然,十分具有普适性了。
	int N, S, M, K;
	Player *p;					//循环指针
	cout << "为了让游戏更加具有普适性,定义为:现有N人围成一圈," 
	<< "从第S个人开始依次报数,报M的人出局," << endl;
	cout << "再由下一个人开始报数,如此循环,直到剩下K个人为止。" 
	<< "显然,十分具有普适性了" << endl;
	cout << "请输入生死游戏的总人数N:";
	cin >> N;
	//容错操作
	while(N < 2)
	{
		cout << "至少需要两个人!请重新输入:";
		cin >> N;
	}
	cout << "请输入游戏开始的位置S:";
	cin >> S;
	//容错操作
	while (S > N)
	{
		cout << "错误的位置,请重新输入:";
		cin >> S;
	}
	cout << "请输入死亡数字M:";
	cin >> M;
	//容错操作
	while (M <=0)
	{
		cout << "死亡数字应为正整数,请重新输入:";
		cin >> M;
	}
	cout << "请输入剩余的生者人数K:";
	cin >> K;
	//容错操作
	while (K < 0 && K > N)
	{
		cout << "剩余的生者人数应为正整数且应大于总人数,请重新输入:";
		cin >> K;
	}
	//调用核心函数
	p = solve(N, S, M, K);
	//输出
	cout << "最后剩下:    " << K << "人" << endl;
	cout << "剩余的生者位置为:    ";
	for (int i = 0; i < K; i++) 
	{
		cout << p->pos << "    ";
		p = p->Next;
	}
	cout << endl;
	cout << "20213002624李季鸿" << endl;
	system("pause");
	return 0;
}

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值