zoukankan      html  css  js  c++  java
  • 算法习题---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函数则继续数据修改。这样为我们后面的调试,和解耦合带来的好处
  • 相关阅读:
    [ jquery 选择器 :hidden ] 此方法选取匹配所有不可见元素,或者type为hidden的元素
    剑指 Offer 03. 数组中重复的数字 哈希
    LeetCode 1736. 替换隐藏数字得到的最晚时间 贪心
    Leetcode 1552. 两球之间的磁力 二分
    Leetcode 88. 合并两个有序数组 双指针
    LeetCode 1744. 你能在你最喜欢的那天吃到你最喜欢的糖果吗?
    LeetCode 1743. 相邻元素对还原数组 哈希
    LeetCode 1745. 回文串分割 IV dp
    剑指 Offer 47. 礼物的最大价值 dp
    剑指 Offer 33. 二叉搜索树的后序遍历序列 树的遍历
  • 原文地址:https://www.cnblogs.com/ssyfj/p/10837780.html
Copyright © 2011-2022 走看看