题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6709
题意:现在有 n n n条鱼,你每抓一条鱼要花费 k k k的时间,烹饪每条鱼至少花费 t i t_{i} ti的时间,你在烹饪的时候可以抓鱼但是不能抓鱼的时候不能分心去换一条鱼继续烹饪,问你花费的时间最少是多少。
解题心得:
- 贪心好题啊,很像以前做过的贪心买股票但是这个还需要想得更多一点。首先明白有一种情况就是 t i t_{i} ti不是 k k k的整倍数,例如 k k k等于 5 5 5, t i t_{i} ti等于 7 7 7时,我是抓 1 1 1条鱼然后等待烹饪结束再去抓鱼,还是让鱼烹饪 10 10 10分钟我抓两条鱼。这个时候就需要看情况了,首先假设我现在手里有很多鱼这个时候我不急着抓鱼,我可以等着鱼烹饪结束然后再去抓鱼。如果这个时候我手里没鱼了,我肯定要去抓鱼而不是等待烹饪结束。
- 因为我要鱼尽可能的多我肯定先捕烹饪时间长的鱼,将烹饪时间降序排序,我就趁这个烹饪时间使劲抓鱼,但是如果没有烹饪时间长的鱼咋办,这个时候我要抓让我浪费时间最少的鱼,这时贪心策略就是一个回溯的过程,将我之前抓的鱼浪费的时间都记录下来,现在鱼不够我就在前面我浪费时间最多的情况下再花一点时间多捕一条鱼。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+100;
ll n, k, sum, num[maxn];
priority_queue <ll> qu;
void init() {
scanf("%lld%lld", &n, &k);
for (int i = 1; i <= n; i++) {
scanf("%lld", &num[i]);
}
sort(num+1, num+1+n);
reverse(num+1, num+1+n);
}
int main() {
// freopen("1.in.txt", "r", stdin);
int t; scanf("%d", &t);
while(t--) {
init();
ll head = 1;
sum = k;
for(int i=1;i<=n;i++) {
sum += num[i];
qu.push(num[i]%k);
head += num[i]/k;
if(head < i) {
sum += k - qu.top();
qu.pop();
}
}
while(!qu.empty()) qu.pop();
printf("%lld\n", sum);
}
return 0;
}