题目大意:
T组输入, 每组输入第一行 n, k 分别是鱼的个数,和钓鱼的所用时间。 下面一行n个数代表炖好第 i 条鱼所用时间。
可以在炖鱼的时候去钓鱼,也可以在钓鱼的时候去炖鱼,但是不能在钓鱼的过程中回去重新炖其他鱼。求最短完成时间。
思路:
烹饪一条鱼结束前,能把鱼钓上来,是最理想的情况。因此先求出能在每次烹饪过程结束前钓出来几条鱼:cnt += ti / k(i = 1~n),cnt = min(cnt, n)。不能在每条鱼烹饪结束前钓上来的鱼数量就是 n - cnt - 1(第一条鱼必须先钓,不能在烹饪过程中进行,所以先减去)。
将每个烹饪时间对钓鱼时间取余,从大到小排序。我们将不能在烹饪结束前就钓上来的鱼,分别安排在这些烹饪时间余数最大的地方,这样重叠时间越多,多出来的时间就会越少。
总时间 = 烹饪总时间 + 钓鱼多出来的时间(烹饪完了,鱼没钓完,多出来的时间)。
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
#define int long long
typedef pair<int, int> PII;
const int Max = 0x3f3f3f3f3f3f3f3f;
const int Min = -0x3f3f3f3f3f3f3f3f;
int n, m, k;
int T;
int ans, cnt, a[N];
bool cmp(int aa, int bb)
{
return aa > bb;
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> T;
while (T--)
{
ans = 0, cnt = 0; //初始化
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
ans += a[i]; //炖鱼的总时间
cnt += a[i] / m; //炖鱼的时候可以钓上来几条鱼
a[i] %= m; //炖完整的鱼之后剩下的时间余数
}
cnt = min(cnt, n); //与总鱼数取小(因为可以炖鱼的数量可能大于总数)
sort(a + 1, a + n + 1, cmp); //将余数从大到小排序
for (int i = 1; i <= n - cnt - 1; i++) //第一条鱼钓上来之前不能炖鱼,要除去第一条鱼,所以是n-cnt-1,
{
ans += m - a[i]; //加上在炖完鱼,但是鱼还没钓完,重叠后多用的时间
}
cout << ans + m << "\n"; //所用时间再加上第一条鱼钓上来的时间
}
return 0;
}