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

    约瑟夫问题
    据说著名犹太历史学家 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();
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于约瑟夫问题,我可以给你提供一个基于数组的 C 语言解决方案。具体思路是:先创建一个长度为 n 的数组,表示有 n 个人参与游戏,然后依次将这些人编号为 1 到 n。接着,从编号为 k 的人开始报数,每报到 m 就将该人从数组中删除,直到数组中只剩下一个人为止。最后剩下的那个人即为胜者。 下面是代码实现: ```c #include <stdio.h> int main() { int n, m, k; printf("请输入参与游戏的人数 n:"); scanf("%d", &n); printf("请输入报数的上限 m:"); scanf("%d", &m); printf("请输入从第几个人开始报数 k:"); scanf("%d", &k); int a[n]; // 创建长度为 n 的数组 for (int i = 0; i < n; i++) { a[i] = i + 1; // 将每个人的编号存入数组中 } int count = 0; // 记录已经报数的人数 int index = k - 1; // 记录当前报数的人在数组中的下标 while (n > 1) { if (a[index] != 0) { // 如果当前报数的人还在数组中 count++; // 已经报数的人数加一 if (count == m) { // 如果已经报数到 m a[index] = 0; // 将该人从数组中删除 count = 0; // 已经报数的人数清零 n--; // 参与游戏的人数减一 } } index++; // 下一个人报数 if (index == n) { // 如果已经报数到最后一个人 index = 0; // 从第一个人重新开始报数 } } for (int i = 0; i < n; i++) { if (a[i] != 0) { // 找到最后剩下的那个人 printf("胜者的编号是:%d\n", a[i]); break; } } return 0; } ``` 你可以根据需要修改代码中的变量名和注释,以便更好地理解和使用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值