救濟金髮放( The Dole Queue, UVa 133)

last_malloc發表於2020-12-07

題目描述:

n(n<20)個人站成一圈,逆時針編號為 1~n。有兩個官員,A從1開始逆時針數,B從n開始順時針數。在每一輪中,官員A數k個就停下來,官員B數m個就停下來(兩個官員有可能能停在同一個人上)。接下來被官員選中的1個或2個人離開隊伍。

輸入格式 輸入n ,k ,m ,可能有多組資料,以 0 0 0結尾。

輸出格式 輸出每輪裡被選中的人的編號(如果有兩個人,先輸出被A選中的)。輸出的每個數應正好佔3列。樣例中的“ ␣ ”代表一個空格。

輸入樣例:

10 4 3
0 0 0

輸出樣例:

␣␣4␣␣8,␣␣9␣␣5,␣␣3␣␣1,␣␣2␣␣6,␣10,␣␣7

思路:一圈n個人可以看成一個迴圈佇列,設定n個標誌位來表示某個人有沒有被選中並離開隊伍,只有標誌位為false的元素才是迴圈佇列的有效元素。設定兩個遊標表示官員A和B當前所指向的元素,每次輸出就是將A的遊標向後迴圈移動k位,B的遊標向前迴圈移動m位(移動過程中跳過無效元素)並輸出,將輸出元素的標誌位設定為false,直至迴圈佇列中所有元素標誌均為false。

個人程式碼:

#include <bits/stdc++.h>

using namespace std;

int main()
{
    int n, k, m, A, B;
    while(cin >> n >> k >> m && n)
    {
        //當前所數到的元素下標
        A = -1, B = n;
        //當前所屬到的元素個數
        int cntA = 0, cntB = 0;
        vector<bool>flagArr(n, false);
        vector<bool>flagTrue(n, true);
        bool flagSta = true;
        while(flagArr != flagTrue)
        {
            if (!flagSta)
                cout << ",";
            flagSta = false;
            //A數到下k個
            while (cntA < k)
            {
                do
                {
                    A = (A + 1) % n;
                }while(flagArr[A]);
                ++cntA;
            }
            //B數到下m個
            while (cntB < m)
            {
                do
                {
                    B = (n + B - 1) % n;
                }while(flagArr[B]);
                ++cntB;
            }
            cntA = cntB = 0;
            flagArr[A] = flagArr[B] = true;
            if (A == B)
                printf("%3d", A + 1);
            else
                printf("%3d%3d", A + 1, B + 1);
        }
        printf("\n");
    }
    return 0;
}

參考程式碼:

#include<stdio.h>
#define maxn 25
int n, k, m, a[maxn];

// 逆時針走t步,步長是d(-1表示順時針走),返回新位置
int go(int p, int d, int t) {
  while(t--) {
    do { p = (p+d+n-1) % n + 1; } while(a[p] == 0); // 走到下一個非0數字
  }
  return p;
}

int main() {
  while(scanf("%d%d%d", &n, &k, &m) == 3 && n) {
    for(int i = 1; i <= n; i++) a[i] = i;
    int left = n; // 還剩下的人數
    int p1 = n, p2 = 1;
    while(left) {
      p1 = go(p1, 1, k);
      p2 = go(p2, -1, m);
      printf("%3d", p1); left--;
      if(p2 != p1) { printf("%3d", p2); left--; }
      a[p1] = a[p2] = 0;
      if(left) printf(",");
    }
    printf("\n");
  }  
  return 0;
}

 

相關文章