约瑟夫问题(数组形式以及向量形式)的解决方式

本文介绍了约瑟夫问题的历史背景及其解决方法,通过数组法和向量法两种算法实现,展示了如何找到最后生存者的编号。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    约瑟夫问题
    据说著名犹太历史学家 Josephus 有过以下的故事:在罗马人占领乔塔帕特后,
    39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不
    要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开
    始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有
    人都自杀身亡为止。然而 Josephus 和他的朋友并不想遵从,Josephus 要
    他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过
    了这场死亡游戏。
    

//数组法
/************************************************************************************************************/
/*
函数名:Josephus
参数:
1.Number         游戏的人数
2.group          小组人数
返回值: Player_number 幸存玩家编号
*/
/************************************************************************************************************/
int *Josephus(int number,int group)
{
	bool *persons=new bool[number];
	for(int i=0;i<number;i++)
		persons[i]=true;
	int counter=number,index=0,numbertt=0;
	while(counter >= group)
	{
		if(persons[index]==true)
		{
			numbertt+=1;
			if(numbertt==group)//到三号时
			{
				persons[index]=false;
				counter-=1;
				numbertt=0;//计数置零
			}	
		}
		index+=1;
		index%=number;
	}
	int *Player_number=new int[group-1];
	int j=0;
	for(int i=0;i<number;i++)
	{
		if(persons[i]==true)
		{
			Player_number[j]=i+1;
			j++;
		}
	}
    delect[] persons;
	return Player_number;
}



向量法
/************************************************************************************************************/
/*
函数名:Josephus
参数:
1.Number         游戏的人数
2.group          小组人数(就是多少人一循环,比如约瑟夫问题中就是3人一个循环)
3.Player_number  幸存玩家编号
返回值: void
*/
/************************************************************************************************************/
void Josephus(int Number,int group,vector<int> &Player_number)
{
    int m=0;
	int index=0;//记录本轮不完整三人组人数
	for (int i=1;i<=Number;i++)//记录所有人编号,从1开始编号
		Player_number.push_back(i);
	for (int i=1;;i++)
	{
		if(i%group==0) Player_number[m]=0;//标记死亡人编号
		m++;//
		if(m==Number)//判断当前此轮是否完成
		{
			m=0;//本轮完成向量索引置0
			i=(Number-(group-index))%group;//本轮人数减去本轮轮尾三人组的人数除以三取余得到下一轮轮首不完整三人组人数
			index=i;//轮首不完整三人组人数
			for (int j=0;j<Player_number.size();j++)//删除死亡人编号
			{
				if (Player_number[j]==0) Player_number.erase(Player_number.begin()+j);	
			}
			Number=Player_number.size();//记录还剩多少人
		}
		if (Player_number.size()<=group-1)break;
	}
}

void main()
{

    //数组法
    int *pnumber=Josephus(41,3);
	for(int i=0;i<2;i++)
		cout<<pnumber[i]<<endl;
	delete[] pnumber;

    //向量法
	vector<int> Player; 
	Josephus(41,3,Player);
	for (int i=0;i<Player.size();i++)
	{
		cout<<Player[i]<<endl;
	}
    Player.clear();
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值