约瑟夫环(joseph环)——经典算法
由多个玩家围成一个圈从一号玩家开始按顺时针杀掉下一名玩家,直到剩下最后一名,则该玩家获胜
对于此问题我们可以用一维数组的思想模拟出解法
代码如下:
#include<iostream>
using namespace std;
#define H 10005
int a[H];
int main()
{
int d = 1, n, i;
int c = 1;
cout << "请输入参加游戏人数:" << endl;
cin >> n;
cout << "依次出局的编号为:";
while (c <= n)
{
for (i = d; i < 2 + d; i++)
{
if (i > n) { i -= n; d -= n; }
if (a[i])d++;
}
i--;
cout << i << " ";
a[i] = 1;
d = i + 1;
c++;
}
cout << endl << "最后获胜的玩家是:" << i;
}
核心代码:
for (i = d; i < 2 + d; i++)
{
if (i > n) { i -= n; d -= n; }
if (a[i])d++;
}
i--;
cout << i << " ";
a[i] = 1;
d = i + 1;
i
:作为指针指向玩家。d
:作为每次被淘汰的下一位玩家(可以理解为从d号玩家开始算起),d的初始值设为1。f (i > n) { i -= n; d -= n; }
检测下标,若超出范围将下标i
和d
跳转为1号玩家。if (a[i])d++;
判断该玩家如果被淘汰(若为空则未淘汰,反之淘汰)将i的循环次数多加一次(当作跳过该玩家)。i--;
为了辅助for (i = d; i < 2 + d; i++)
该循环在结束循环后会移动到被淘汰玩家的后一位玩家,为了避免这种错误,在打印淘汰者前会向前退一位。a[i]=1;
将该玩家判定为被淘汰状态。d=i+1;
移动到被淘汰的下一位玩家。
约瑟夫环——变种算法
编号是1,2,……,n的n个人按照顺时针方向围坐一圈,一开始任选一个正整数作为报数上限值m(m<n),从第s(s<n)个人开始沿顺时针方向自1开始顺序报数,报到m时停止报数。报m的人出列,将他的编号作为新的m值,从他在顺时针方向的下一个人开始重新从1报数,如此下去,直到所有人全部出列为止
该问题与经典约瑟夫环的不同就是上限从2变为任意并且开始编号从1号变为任意。
所以我们只需要在基础算法上多定义一个上限值和初始编号即可。
代码如下:
#include<iostream>
using namespace std;
#define H 10005
int a[H];
int main()
{
int count, d,n,i;
int c=1;
cout << "请输入参加游戏人数:" << endl;
cin >> n;
cout << "请输入第一次的上限为多少:" << endl;
cin >> count;
cout << "请输入从几号开始:" << endl;
cin >> d;
cout << "依次出局的编号为:";
while (c<=n)
{
for ( i = d; i < count+d; i++)
{
if (i > n) { i -= n; d -= n; }
if (a[i])count++;
}
i--;
cout << i << " ";
a[i] = 1;
count = i;
d = i + 1;
c++;
}
}
count
:为每次的上限值。(上限初始值为玩家输入)