算法:围圈报数类问题的经典解题思路

时间:2021-04-12 12:09:35   收藏:0   阅读:0

算法:围圈报数类问题经典解题思路

大概题型如下:
描述

有n个人依次围成一圈,从第1个人开始报数,数到第m个人出列,然后从出列的下一个人开始报数,数到第m个人又出列,…,如此反复到所有的人全部出列为止。设n个人的编号分别为1,2,…,n,
打印出列的顺序。

格式
输入格式

n和m。

输出格式

出列的顺序。

样例
输入样例

4 17

输出样例

1 3 4 2

限制
时间限制: 1000 ms
内存限制: 65536 KB

解题代码:(虽然我也是“拿来主义者,但有时还是要有点追求,建议看下代码下面的原理”)

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <math.h>
using namespace std;

int main()
{
    int n,m;
    int num=1;//计数器
    int peopleNum=0;//人数
    int index=0;
    int t[10240]={0};
    scanf("%d %d",&n,&m);
    while(1)
    {
        if(t[index]==0)//等于0,表示人还在
        {
            if(num%m==0)
            {
                //printf("%d %d %d\n",num,m,index);
                t[index]=1;
                printf("%d ",index+1);
                peopleNum++;
            }
            num++;
        }
        index++;
        if(index>=n) index=0;
        if(peopleNum==n) break;
    }
    return 0;
}

这只是这么多这种题型中的一道,所以要掌握的是这种题的解题套路以及相关相关思想。
解题套路级思想:
在这种题中,表述的内容无非不就是,n个人围成圈,然后报数,那么题目是没有给我们具体循环次数的,从一开始就决定了不能使用for循环,所以选择用while,个人比较喜欢写死循环while(1)在写跳出循环方法if(peopleNum==n) break;,当然你也可以写成while(peopleNum!=n).
然后进入关键部分,在本题中需要一个计数器num,一个下标index,一个进行标记的数组,进入循环后,首先应该判断负责标记的数组,标记的作用是判断人是否还在圈内,在则进行报数,报的数字可以被要求数字整除,将其出列(标记数组改为1),如果不能被整除,则跳过。这里有个小细节!!!只有在队列的数组才可以报数,所以计数器也只有人还在队列时才会自加,所以计数器必须放到标记数组判断的范围内。接下来就是一个下标自加,如果越界就变回0.至此整个思路和代码结束

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!