第四章 - The Dole Queue - uva 133

本文介绍了一个模拟裁员过程的算法实现,该算法通过特定的规则选择人员进行“再培训”,即模拟从待业队伍中挑选人员的过程。算法实现了双向计数选择,并在每次选择后更新剩余人数,直至无人被选。

In a serious attempt to downsize (reduce) the dole queue, The New National Green Labour RhinocerosParty has decided on the following strategy. Every day all dole applicants will be placed in a largecircle, facing inwards. Someone is arbitrarily chosen as number 1, and the rest are numbered counterclockwiseup to N (who will be standing on 1’s left). Starting from 1 and moving counter-clockwise,one labour official counts off k applicants, while another official starts from N and moves clockwise,counting m applicants. The two who are chosen are then sent off for retraining; if both officials pickthe same person she (he) is sent off to become a politician. Each official then starts counting againat the next available person and the process continues until no-one is left. Note that the two victims(sorry, trainees) leave the ring simultaneously, so it is possible for one official to count a person alreadyselected by the other official.InputWrite a program that will successively read in (in that order) the three numbers (N, k and m; k, m > 0,0 < N < 20) and determine the order in which the applicants are sent off for retraining. Each set ofthree numbers will be on a separate line and the end of data will be signalled by three zeroes (0 0 0).OutputFor each triplet, output a single line of numbers specifying the order in which people are chosen. Eachnumber should be in a field of 3 characters. For pairs of numbers list the person chosen by the counterclockwiseofficial first. Separate successive pairs (or singletons) by commas (but there should not be atrailing comma).Note: The symbol ⊔ in the Sample Output below represents a space.Sample Input10 4 30 0 0Sample Output␣␣4␣␣8,␣␣9␣␣5,␣␣3␣␣1,␣␣2␣␣6,␣10,␣␣7

分析:

看似简单,可废了不少时间去写……怎么去设计函数,使代码简洁高效是我们需要考虑的。

注意,每次两个人选人的时候,比如:a从1到6选了6(k=6),这时,6还没有被移去,b从10选到5(m=6)6也算进去

注意,怎么构造go函数使得,正序,逆序都可以调用到它是很重要的。

之前写的代码,每进行一轮挑选,就用一个从1到n的for循环,判断是否都被选完……这个做法是非常蠢的。

定义一个变量记录还剩的人数,当变量为0是退出就行了。(这是我从这道题学到的方法)

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;
int n,k,m;
int a[25];

int go(int pos,int turn,int x){//从pos开始向turn方向走x步
    for(int i=pos;;i=(i+turn)%n){
        if(i==0)i=n;
        if(a[i]!=0&&x!=0)x--;
        if(x==0)return i;
    }
}
int main(){

    while(scanf("%d%d%d",&n,&k,&m)!=EOF){
        if(n==0&&k==0&&m==0)break;
        int left=n;
        for(int i=1;i<=n;i++){
            a[i]=i;
        }
        int l=0,r=n+1;
        while(left){
            l=go(l+1,1,k);
            r=go(r-1,-1,m);
            if(l==r)left--;
            else left-=2;
            if(l==r){printf("%3d",a[l]);a[l]=0;}
            else {printf("%3d%3d",a[l],a[r]);a[l]=0;a[r]=0;}
            if(left!=0)printf(",");
            else printf("\n");
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值