開啟章節選單

10273 Eat or Not to Eat?

題目連結

題目敘述

一位年輕的農夫有 N 頭奶牛,但牠們產的牛奶量實在非常非常少
John 無法僅靠這些少量的牛奶維生
所以他打算吃掉其中「表現最差」的幾頭牛以度過饑餓
每天 John 會選出當天產奶量最少的那頭牛並將其吃掉
如果當天有多頭牛並列為最低產奶量
John 會因為猶豫不決而不會吃任何牛(耶!太好了!)。

第 i 頭牛的產奶週期為 Ti
也就是說,若牠在某天產了 L 單位的牛奶
那麼在 Ti 天後,若牠尚未被吃掉
將會再度產 L 單位的牛奶。

雖然 John 並不聰明
但他懷疑所有牛最終是否都會被吃光,因此請你幫助他
別忘了,他會提供一些美味的牛肉作為回報!

輸入說明

輸入的第一行包含一個整數 T,表示測試案例的數量(1 ≤ T ≤ 50)。
每個測試案例先有一行整數 N(1 ≤ N ≤ 1000),代表奶牛的數量。
接下來有 N 行,對應第 i 頭牛:

  • 首先是一個整數 Ti(1 ≤ Ti ≤ 10),表示該頭牛的產奶週期;
  • 接著有 Ti 個整數 Mj(0 ≤ Mj ≤ 250),分別表示該頭牛在週期內第 j 天所能產的牛奶量。

輸出說明

對於每個測試案例,輸出一行,包含兩個整數 C、D:

  • C:最終不會被吃掉的奶牛數量;
  • D:當最後一頭被吃掉的牛被吃掉時,已經過的天數。

若沒有任何奶牛被吃掉,則第二個數字請輸出 0。

程式碼

#include <bits/stdc++.h>
using namespace std;

#define INF LONG_LONG_MAX / 1000
#define int long long

signed main() {
  int t;
  cin >> t;
  while (t--) {
    int n, m, tmp;
    cin >> n;                  // 讀取牛隻總數 N
    vector<vector<int>> v(n);  // 使用二維陣列 v 存放每頭牛的週期性生產量
    for (int i = 0; i < n; i++) {
      cin >> m;  // 讀取第 i 頭牛的生產週期長度 Ti
      while (m--) {
        cin >> tmp;           // 讀取週期中某一天的產量
        v[i].push_back(tmp);  // 將該天產量加入第 i 頭牛的資料陣列
      }
    }

    // lastday:最後一次宰殺動作發生的天數(0-base)
    // cnt:已宰殺牛隻總數
    int lastday = -1, cnt = 0;
    vector<int> kill(n);  // kill[i] = 1 表示第 i 頭牛已被宰殺,否則為 0
    for (int day = 0; day - lastday <= 2520;
         day++) {  // 模擬每日作業,終止條件:自上次宰殺日起連續 2520 天(Ti 跟
                   // Mj 的最小公倍數)內未再發生宰殺
      int mn = INF;    // 當日檢測到的最小產量
      int cowID = -1;  // 對應最小產量的牛隻索引
      for (int i = 0; i < n;
           i++) {  // 遍歷所有尚未被宰殺的牛隻,尋找當日唯一最少產量
        if (kill[i]) continue;               // 牛被殺掉就跳過
        int milk = v[i][day % v[i].size()];  // 以 day % 週期長度 取當日產量
        if (milk < mn) {  // 發現更小產量時,更新最小值及對應牛隻索引
          mn = milk;
          cowID = i;
        } else if (milk == mn)
          cowID = -1;  // 若有多頭牛隻產量相同且為最小,標註為無法確定唯一最少
      }
      if (~cowID) {  // 若存在唯一最少產量的牛隻,則進行宰殺動作
        kill[cowID] = 1;  // 標記該牛隻已被宰殺
        lastday = day;    // 更新最後一次宰殺的天數索引
        cnt++;            // 累計宰殺數量
      }
    }
    cout << n - cnt << ' ' << lastday + 1 << '\n';  // 最後輸出
  }
}