约瑟夫环问题

问题描述

  • 33个人围成一圈,从1开始报数,报到7的人“死亡”,下一个人重新从1开始报数,以此类推,直至剩余最后一个人。求出最后一个人的编号

程序设计思路

  • 程序只不过是思维的体现工具,可以这么来说,所有的编程语言不过是编程思维的一种体现而已。因此,在写程序之前,程序的设计思路是相当重要的。
  • 此程序需要解决几个问题:

    • 需要一个长度为33的数组,数组中存的是什么
    • 怎么实现循环报数
    • 怎么实现“逢7死亡”的逻辑
    • 怎么处理“死亡之人”
  • 既然已经使用了数组来存储,那么数组下标完全可以作为每个人的编号。那么,我们可以在数组元素中使用一个状态位来标记此人是“DEAD”or“ALIVE”

  • 给定一个变量用于统计当前的人数。

if(k == 33)
    k = 0;
  • 实现“逢7死亡”
    • 总共有33个人,最后只能有一个人存活,也就是说,有32个人“死亡”,这32个人都是报数报到7的人。
    • 对于以上分析,我们不难看出,该程序采用的语句结构是双重for循环。
    • 外层循环控制“死亡”的总人数,内层循环控制每隔7个人“死亡”。
  • 处理“死亡之人”
    • 对于“死亡之人”的处理是该程序设计的一个重难点所在。
    • 报到7的人“死亡”,但是仍然存在于数组中,因此在下一次循环报数的时候又会轮到此人报数,这样的话就会导致报数错误。
    • 我们可以这样处理:如果“死亡之人”参与了报数,那么我们就把报数的数字减1,即忽略掉“死亡之人”的报数。这样既不会影响外层循环,也不会影响到内层循环。
    • 该过程的部分伪码如下:
int i, j;
int k = -1;
int a[33];
for(i=0;i<32;i++)
{
    for(j=0;j<7;j++)
    {
        k++;
        if(a[k] == "DEAD")    //“死亡之人”的处理
            j--;
        if(K == 33)     // 循环报数
            k = 0;
    }
    a[k] = "DEAD";   //逢7“死亡”
}

程序实现

约瑟夫环问题的C语言完整代码如下:

#include
#define N 33        //参与报数的总人数
#define M 7         //报数到该数字的人退出
#define DEAD 1
#define ALIVE 0

int
main()
{
    int a[N] = {ALIVE};
    int i, j, k = -1;

    for(i = 0; i < N - 1; i++)
    {
        for(j = 0; j < M; j++)
        {
            k++;
            if(k == N)      //实现循环报数
                k = 0;
            if(a[k] == DEAD)    //“死亡之人”的报数处理
                j--;
        }
        a[k] = DEAD;        //逢7“死亡”
    }
    for(i = 0; i < N; i++)
        if(a[i] == ALIVE)
            printf("%d\n", i + 1);
    return 0;
}

你可能感兴趣的:(编程语言,编程语言)