欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

第四章 - The Dole Queue - uva 133

程序员文章站 2022-03-17 13:01:51
...

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");
        }
    }
}

相关标签: acm 函数的调用