算法习题---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("\n");
    }

    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函数则继续数据修改。这样为我们后面的调试,和解耦合带来的好处

 

作者:山上有风景
欢迎任何形式的转载,但请务必注明出处。
限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。

posted @   山上有风景  阅读(411)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
历史上的今天:
2018-05-09 python---基础知识回顾(十)进程和线程(多线程)
2018-05-09 python---方法解析顺序MRO(Method Resolution Order)<以及解决类中super方法>
点击右上角即可分享
微信分享提示