• 算法习题---4.3救济金发放(UVa133)


    一:题目

    (n<20 )个人站成一圈,逆时针编号为1~n。
    有两个官员,A从1开始逆时针数,B从n开始顺时针数
    在每一轮中,官员A数k个就停下来,官员B数m个就停下来(注意有可能两个官员停在同一个人上)。接下来被选中的人离开队伍。 输入n,k,m输出每轮被选中的人的编号(如果有两个人,先输出A的)每个输出数字正好占3列。

    二:实现思路

    A从数组首部向后遍历(若是该位置还有人,则步数加一,否则不改变步数),当遍历到最后,则转回首部继续遍历。
    B从数组尾部向前遍历(...),若是遍历到首部,则转回尾部继续向前遍历

    三:代码实现

    int member[21] = { 0 };    //为了方便理解,从下标1开始到下标20被利用
    int n, k, m;
    
    /*
    input:
        int pos        //当前位置
        int dict    //谁要走
        int step    //走的步数
    output:
        走之后的当前位置
    */
    int donate(int pos, int dict, int step)
    {
        while (step--)
        {
            do 
            {
                pos = (pos + dict + n - 1) % n + 1;
            } while (member[pos]==0);
        }
        return pos;
    }
    
    void func04()
    {
        freopen("data.in", "r", stdin);
        freopen("data.out", "w", stdout);
    
        while (1)
        {
            //开始读取数据
            scanf("%d%d%d", &n, &k, &m);
            if (n == 0 && k == 0 && m == 0)
                break;    //结束
    
            int pos1 = n, pos2 = 1, count = n;
    
            //将对应人数置为1,表示没有领取救济金
            for (int i = 1; i <= n; i++)
                member[i] = 1;
    
            while (count)
            {
                pos1 = donate(pos1, 1, k);
                pos2 = donate(pos2, -1, m);
    
                printf("%3d", pos1);
                count--;
                if (pos1 != pos2)
                {
                    printf("%3d", pos2);
                    count--;
                }
                member[pos1] = member[pos2] = 0;
                if (count)
                    printf(", ");
            }
            printf("
    ");
        }
    
        freopen("CON", "r", stdin);
        freopen("CON", "w", stdout);
    }

    四:代码分析

    (一):位置计算

    pos = (pos + dict + n - 1) % n + 1;
    当方向dict为正数时,pos + dict + n - 1 = pos+n
    故pos = (pos+n)%n + 1向前走一步pos在(1,n)范围
    当dict为负数时,pos + dict + n - 1 = pos+n-2
    pos = (pos+n-2)%n+1 = pos - 2+1 = pos-1;向后走一步pos范围在(1,n)

    (二):初始值

    pos1 = n, pos2 = 1
    我们传递到处理函数中的位置初值,应该是我们开始处理的前一个数据。
    我们返回应该处理的数据的位置

    五:应该将逻辑和数据分开《重点》

    donate函数只复制找到我们需要处理的位置,main函数则继续数据修改。这样为我们后面的调试,和解耦合带来的好处
  • 相关阅读:
    linux定时备份数据库
    svn 没有绿色小勾
    oracle dblink ora-12541 无监听
    WPS 设置多级标题
    sql 提高速度方法
    领骑衫获奖感言与总结
    团队项目(任务五):项目回顾
    项目回顾
    团队项目(任务四):第二次冲刺
    团队项目(任务三):第一次冲刺
  • 原文地址:https://www.cnblogs.com/ssyfj/p/10837780.html
Copyright © 2020-2023  润新知