Joseph의 problem_C 언어 구현의 고전적인 문제

<조셉 질문>

1. 문제에 대한 간략한 설명

Joseph 문제는 수학적 응용 문제인 Joseph ring이라고도합니다.

번호를보고 한 첫 번째 사람부터 시작하여 원 안에 n 명의 사람 (각각 1, 2, 3 ... n)이 앉아 있고, 그 번호로보고하는 사람의 수가 밖으로 나가는 것으로 알려져 있습니다. 다음 사람부터 시작하여 다시보고하고보고합니다. m을 가진 사람은 서클에서 나가고 마지막 사람이 남으면 게임이 종료됩니다. 남은 사람의 원래 번호를 출력합니다.

2. 질문 사고

우리가 해결하고자하는 문제 :

  • m에게보고하는 사람은 원을 벗어났습니다. 그가 원을 벗어났다는 것을 어떻게 표시합니까?
  • 문제를 해결 한 후 원에서 벗어나는 방법은 무엇입니까? 다른 레이블을 사용하여 어레이의 연속성을 보장하거나 상태 플래그를 설정하기 위해 앞으로 나아가 야합니까?
  • 배열은 선형입니다. 어떻게 원으로 연결합니까?

3. 두 가지 대체 구현 방법

방법 1 :

방법 : 먼저 각 계산 라운드에서 서클을 벗어나야하는 사람 (m에 등록한 사람)의 위치를 ​​찾습니다. 한 사람이 서클을 벗어나면 다음 레이블을 차례로 앞으로 이동하고 반복합니다. 마지막 사람이 남을 때까지.

참고 : 각 사람의 원래 번호 기록, 배열에서 원을 떠난 사람의 위치 검색, 뒤에있는 사람의 움직임 ...

구체적인 코드는 다음과 같습니다.

#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;
}
방법 2 :

방법 : 카운트 카운트를 설정하고, 사람이 서클을 떠날 때마다 카운트를 0으로 설정하고, 매번 서클을 떠난 사람 이후에 카운트를 0으로 설정하면 서클을 떠나는 다음 사람이 계속 1부터 카운트합니다.

참고 : 각 사람이 원을 벗어난 후 총 사람 수는 -1이므로 원래 데이터 n이 파괴되는 것을 방지하기 위해 변경에 n 대신 x가 사용됩니다. 원래 숫자를 출력 할 때 배열에서 0이 아닌 사람을 찾으세요 ~
ps : 방법 1은 또한 동그라미로 표시된 사람의 위치를 ​​찾기 위해 계수 방법을 사용할 수 있습니다 ~

구체적인 코드는 다음과 같습니다.

#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;
}

팁 : Joseph 문제는 재귀정산 목록사용할 수도 있습니다 .

추천

출처blog.csdn.net/qq_51366851/article/details/113060404