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