请大神帮忙解答一个初学者接触的C语言问题

设计程序解决问题:
有100个人按编号1~100排成一队,从1开始按1-2-3-1-2-3报数,凡报到3者退出队列,直至报数到队尾,然后又从队尾从1开始,按上述规律报数,仍是报到3的人退出队列,如此反复,直至队列中仅剩两人,求这两人的初始编号。

此外,有两个问题请着重详细解答:1.如何标记退出的人 2.如何表示从1开始报数

请大神们帮忙解答,万分感谢!

用数组存储,建立一个100个元素的数组

int a[100]={0};

0表示未出列,1表示已出列

用2重循环,外层循环98次,代表出列98个人。里层循环3次,代表1-2-3的报数

每次里层循环结束找到一个人,如果这个数组元素是0,则置1;如果是1,则找他下一个不是1的人置1

具体代码如下:

#include <stdio.h>

#include <stdlib.h>

#define MAX 100

#define LIVE 0

#define DEAD 1

int main()

{

    int a[MAX]={LIVE};

    int i,j;

int count = -1;

    for(i=0;i<MAX-2;i++)

    {

        for(j=0;j<3;j++)

        {

            count++;

            if(a[count]==1)

            {

                j--;

            }

            if(count==MAX)

            {

                count=0;

                while(1)

                {

                    if(a[count]==1)

                    {

                        count++;

                    }

                    else

                    {

                        break;

                    }

                }

            }

        }

        a[count]=1;

        printf("第%d号已出列\n",count+1);

    }

    for(i=0;i<MAX;i++)

    {

        if(a[i]==0)

        {

            printf("第%d号是幸存者!\n",i+1);

        }

    }

    return 0;

}

这个题是约瑟夫环问题的变种问法。自己百度“约瑟夫环”问题解法很多

追问

我有这样的思路,但苦于是在写不出程序,请帮忙写一个程序,便于我观察学习,多谢了

追答

代码见上

追问

我仔细看了一下,你写的这个是类似于坐成一圈,按一个方向报数,这个题目要求是报到100号,然后从100号开始向1号的方向报。

温馨提示:答案为网友推荐,仅供参考
第1个回答  2015-11-05
#include <stdio.h>

#define    ARRAYLENGTH    100   //队伍长度
#define    NUMBER         3     //计数周期,即1、2、3
#define    OUTHERE        -1    //标记队员退出队列
#define    SUCCESSNUMBER  2     //最终剩余人数

/* 初始化队员编号,编号从1开始 */
void init_int_array(int * arr, int length);
/* 打印当前队员情况,-1为标记退出 */
void show_int_array(int * arr, int length);
/* 判断当前队员是否是min个 */
int is_end_array(int * arr, int length, int min);
/* 数数并标记退出队员 */
void calc_mark(int * arr, int length, int number);
/* 打印剩下队员的初始编号 */
void show_default_number(int * arr, int length);

int main(void)
{
    int arr[ARRAYLENGTH];
    
    init_int_array(arr, ARRAYLENGTH);//初始化数组,即队伍编号
    show_int_array(arr, ARRAYLENGTH);//打印数组,即队伍情况
    
    while (!is_end_array(arr, ARRAYLENGTH, SUCCESSNUMBER)) {
        calc_mark(arr, ARRAYLENGTH, NUMBER);//标记退出的队员
        show_int_array(arr, ARRAYLENGTH);//打印数组,即队伍情况
    }
    
    printf("The Result Is:\n");
    show_int_array(arr, ARRAYLENGTH);//最终报数完成后队伍情况
    
    show_default_number(arr, ARRAYLENGTH);//打印剩余队员的原始编号
    
    return 0;
}

void init_int_array(int * arr, int length)
{
    for (int i = 1; i <= length; i++) {
        *(arr + i - 1) = i;//给第i-1个队员编号
    }
}

void show_int_array(int * arr, int length) {
    for (int i = 0; i < length; i++) {
        printf("%3d, ", *(arr+i));//输出每个队员的编号,编号占3个字符宽度,如100输出为"100, ",2输出为"  2, "
        if ((i + 1) % 10 == 0) {//输出10个即换行
            printf("\n");
        }
    }
}

int is_end_array(int * arr, int length, int min) {
    int size = 0;//未退出队员计数器
    
    for (int i = 0; i < length; i++) {
        if (*(arr+i) != OUTHERE) {//判断未退出队员则计数器加1
            size++;
        }
    }
    
    size = (size == min) ? 1 : 0;//剩余队员为min个则返回1,反之返回0
    
    return size;
}

void calc_mark(int * arr, int length, int step) {
    int count = 0;
    
    for (int i = 0; i < length; i++) {
        if (*(arr + i) != OUTHERE) {//还未退出的队员
            count++;//队员未退出,计数器加1
        }
        if (count % step == 0) {
            *(arr + i) = OUTHERE;//数到3的则标记为退出
        }
    }
}

void show_default_number(int * arr, int length)
{
    printf("剩余队员的初始编号为:\n");
    for (int i = 0; i < length; i++) {
        if (*(arr + i) != OUTHERE) {
            printf("%d\n", (i+1));
        }
    }
}