<Question de Joseph>
1. Brève description du problème
Le problème de Joseph est également appelé anneau de Joseph, qui est un problème d'application mathématique.
On sait qu'il y a n personnes (respectivement numérotées 1, 2, 3 ... n) assises en cercle, à partir de la première personne à déclarer le nombre, et le nombre de personnes qui se rapportent au nombre m sort de le cercle; puis recommencez à partir de la personne suivante pour signaler à nouveau et signaler La personne avec m sort du cercle; le jeu se termine lorsque la dernière personne est laissée. Sortez le numéro d'origine de la personne restante.
2. Réflexion sur les questions
Le problème que nous voulons résoudre:
- La personne qui rapporte à m est hors du cercle, comment indiquer qu'elle est hors du cercle?
- Après avoir résolu le problème, comment sortir du cercle? S'agit-il d'utiliser d'autres étiquettes pour avancer pour assurer la continuité de la baie, ou pour définir l'indicateur d'état?
- Le tableau est linéaire, comment le connecter en cercle?
3. Deux méthodes de mise en œuvre alternatives
première méthode:
Méthode: trouvez d'abord la position de la personne qui devrait être hors du cercle (la personne qui s'est inscrite pour m) à chaque tour de comptage. Une fois qu'une personne est sortie du cercle, déplacez les étiquettes suivantes vers l'avant à tour de rôle et bouclez jusqu'à ce que la dernière personne soit laissée.
Remarque: l'enregistrement du numéro d'origine de chaque personne, la recherche de la position de la personne qui a quitté le cercle dans le tableau, le mouvement de la personne derrière ...
Le code spécifique est le suivant:
#include <stdio.h>
#define N 100
int main()
{
int n,m=3,s=1;//n:总人数,m:报数值,s报数人的起始编号
scanf("%d",&n);
int a[N] = {
0};//数组初始化
int i,j;
for(i = 0; i < n; i++)//数组遍历
{
a[i] = i+1; //i是数组的位置量,a[i]是每个人的原始编号(从1开始)
}
i=s-1; //数组的起点(0)
while (n > 1)
{
i = (i+m-1) % n; //出圈的人在数组中的位置
for(j = i+1; j < n; j++)
{
a[j-1] = a[j];
}
n--; //出局1人后,总人数-1
if(i == n) //终点后,开始起点(围成一个圈)
{
i = 0;
}
}
printf("%d\n", a[i]);//输出留下的人的原始编号
return 0;
}
Deuxième voie:
Méthode: définissez un décompte, réglez le décompte sur 0 chaque fois qu'une personne quitte le cercle, réglez le décompte sur 0 après la personne qui quitte le cercle à chaque fois, puis la prochaine personne qui quitte le cercle continuera à compter à partir de 1 ;
Remarque: Étant donné que le nombre total de personnes après que chaque personne est sortie du cercle est de -1, afin d'éviter que les données d'origine n soient détruites, un x est utilisé au lieu de n pour le changement. Lors de la sortie du nombre d'origine, il suffit de savoir qui n'est pas 0 dans le tableau ~
ps: La méthode 1 peut également utiliser la méthode de comptage pour trouver la position de la personne encerclée ~
Le code spécifique est le suivant:
#include <stdio.h>
#define N 50
int main()
{
int a[N], m, n, x, i, count = 0;
printf("Please input n m:\n");
scanf("%d %d", &n, &m); //输入总人数n和出局要报的数m
x = n; //把n赋给x,防止使用时n被修改
for (i = 1; i <= n; i++) //数组遍历,此时在数组中的位置就是人原来的编号
{
a[i] = i;
}
while(x>1)
{
for (i = 1; i <= n; i++)
{
if (a[i] != 0) //判断是否出圈,已经出局的就不用报数了
{
count++; //报数
}
if (count == m)
{
a[i] = 0; //出圈的人置为0,而后不参与报数
count = 0;
x--; //出圈一个,总人数减1
}
}
} //循环结束后,出圈的人都已经被置为0,留下唯一一个人
for (i = 1; i <= n; i++)
if(a[i]!=0)
printf("%d ",i); //输出留下的人的原始编号
return 0;
}
CONSEIL: Les problèmes Joseph peuvent également utiliser la récursivité et la liste de règlement.