Facebook Hacker Cup 2016 Round 1 Laundro, Matt

Facebook Hacker Cup 2016 Round 1

注意

Laundro, Matt20 points
Choose Output
No output file selected

Matt Laundro is about to engage in his favourite activity — doing laundry! He's brought L indistinguishable loads of laundry to his local laundromat, which has N washing machines and Mdryers. The ith washing machine takes Wi minutes to wash one load of laundry, and each dryer takes D minutes to dry a load of laundry. At any point in time, each machine may only be processing at most one load of laundry.

As one might expect, Matt wants to wash and then dry each of his L loads of laundry. Each load of laundry will go through the following steps in order:

  1. A non-negative amount of time after Matt arrives at the laundromat, Matt places the load in an unoccupied washing machine i
  2. Wi minutes later, he removes the load from the washing machine, placing it in a temporary holding basket (which has unlimited space)
  3. A non-negative amount of time later, he places the load in an unoccupied dryer
  4. D minutes later, he removes the load from the dryer

Matt can instantaneously add laundry to or remove laundry from a machine. Help Matt minimize the amount of time (in minutes after he arrives at the laundromat) after which he can be done drying all L loads of laundry!

Input

Input begins with an integer T, the number of times Matt goes to the laundromat. For each trip to the laundromat, there is first a line containing the space-separated integers LNM, and D in that order. After that is a line containing N space-separated integers, the ith of which is Wi.

Output

For the ith trip, print a line containing "Case #i: " followed by the minimum time it will take Matt to finish his laundry.

Constraints

1 ≤ T ≤ 50 
1 ≤ L ≤ 1,000,000 
1 ≤ N ≤ 100,000 
1 ≤ M ≤ 1,000,000,000 
1 ≤ D ≤ 1,000,000,000 
1 ≤ Wi ≤ 1,000,000,000 

Explanation of Sample

In the first case, Matt has just one load of laundry. He washes it for 1200 minutes, and dries it for 34 minutes. In the second case, Matt uses the 1-minute washer for both loads of laundry. The second load finishes at the 2-minute mark, so it finishes drying at the 12-minute mark.

Example input · Download
Example output · Download
5
1 1 1 34
1200
2 3 2 10
100 10 1
3 3 3 3
1 2 3
4 2 2 7
5 8
999 1 999 6
3
Case #1: 1234
Case #2: 12
Case #3: 5
Case #4: 22
Case #5: 3003


題意:給L件衣服,n個洗衣機,m個甩幹機。洗衣機一次洗一件衣服,用時wi分鐘,甩幹機甩幹一件衣服

用時D分鐘,洗好的衣服可以放到籃子裏面(此時不計耗時),問洗完並甩幹L件衣服的最少時間。

思路:這個題目開始時候我就想洗衣服,甩乾衣服這些過程之間的規律與聯繫,比如同一洗衣機洗衣時間要求和,

不同的去最大值,來算洗衣時間;甩幹機要在洗衣服的時候甩幹比較省時間。但知道這些還是無法下手。

於是有了另一種方法,問最少時間,是從第一件衣服開始洗計時,最後一件衣服甩幹停止計時。

那其實就是求出每件衣服在儘可能節約時間情況下的總用時,最大的那件衣服的用時就是答案了。

那接下來就是怎麼求出每件衣服在節約時間情況下的總用時了。時間很大,模擬時間線的方法是不現實的。

可以記錄每個洗衣機,每個甩幹機被用了多久,從開始到現在用時最少的則是最早空閒下來可以使用的。

洗衣機n的數量有10萬,線性查找很慢,既然是求最少的一個,可以想到優先隊列。

洗衣機的優先隊列存儲(所用時間,這個洗衣機洗單件衣服的時間),初始時的總時間跟洗一件衣服時間一樣,

開始時就是選洗得最快的。接下來纔是洗得比較快並且空閒下來了的。

答案優先隊列存儲每件衣服整個過程的總用時。

#include <bits/stdc++.h>

const int N = 1e5 + 10;
typedef long long ll;
using namespace std;
int num[N];
typedef pair<ll, int> pli;
void run()
{
  int L, n, m, d;
  scanf("%d%d%d%d", &L, &n, &m, &d);
  for (int i = 0; i < n; i++)
    scanf("%d", num + i);
  
  priority_queue<pli, vector<pli>, greater<pli> >wash;
  priority_queue<ll, vector<ll>, greater<ll> >ans;
  for (int i = 0; i < n; i++)
    wash.push(pli((ll)num[i], num[i]));
  m = min(m, L);//甩幹機很多,但其實如果超過了衣服的數量,多餘的甩幹機是沒有用的,所以取最小值
  for (int i = 0; i < m; i++)
    ans.push(0);
  while (L--)
  {
    pli tmp = wash.top();wash.pop();//讀取的tmp.first是當前洗衣服所能耗費的最小時間
    wash.push(pli(tmp.first + tmp.second, tmp.second));//加上洗衣時間,因爲下一個要用到這個
    ll tim = ans.top(); ans.pop();//洗衣機的衣服就要等當前這件衣服洗完
    ans.push(max(tim, tmp.first) + d);//取最大因爲,可能最早用完的甩幹機可能還沒工作完
  }                                   //此時即使洗完了,也得排隊等着,所以總時間就是最大時間
  ll out;<span style="white-space:pre">			</span>       //加甩干時間
  while(!ans.empty())
  {
    out = ans.top();ans.pop();
  }
  printf("%lld\n", out);
}
int main()
{
#ifndef ONLINE_JUDGE  
    freopen("in.txt","r" ,stdin);
#endif 
    freopen("out.txt","w",stdout);
    // ios::sync_with_stdio(0);
    int T, cas = 1;
    scanf("%d", &T);
    while (T--)
    {
      printf("Case #%d: ", cas++);
      run();
    }
    return 0; 
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章