19 CCPC网络赛第一场1008(贪心)

题意

有n条鱼,你钓一条鱼要k的时间,每条鱼有每条鱼的烹饪时间,问你最少的时间让所有的鱼都烹饪好。

注:钓鱼钓一半的时候不能去切换正在烹饪的鱼。

思路

首先讲两个东西

1、一条鱼(在烹饪的时候我跑去钓鱼)浪费的时间是 k - time%k

2、假设钓鱼没有浪费到我们的时间,我们至少要 a n s = ( k + 所 有 的 鱼 的 烹 饪 时 间 ) ans = (k + 所有的鱼的烹饪时间) ans=(k+)


对所有的鱼从大到小排序,如果花费时间最大的那条鱼的时间<=k,那么答案肯定是 a n s = n ∗ k + a [ n ] ans = n*k + a[n] ans=nk+a[n]
(a[n]是烹饪时间最短的那一条鱼)


对于那些烹饪时间%k==0和烹饪时间大于k的鱼,我们看在不浪费时间的情况下能攒多少条鱼。

1、如果攒下来的鱼大于等于我还没烹饪的鱼的条数,那么没有鱼浪费了我的时间,答案肯定是上面提到的 a n s ans ans

2、如果攒下来的鱼小于我还没烹饪的鱼的条数,我看还欠多少条鱼,然后取对应条数的尽可能少的浪费时间的鱼,就是答案了。

思路大体是这样,代码更容易看懂。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cstdlib>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
ll t[maxn];
bool cmp(ll a, ll b)
{
    return a > b;
}
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int n;
        ll k;
        scanf("%d %lld", &n, &k);
        ll sum = 0;
        for(int i = 1; i <= n; i++)
        {
            scanf("%lld", &t[i]);
            sum += t[i];
        }
        sort(t + 1, t + 1 + n, cmp);//从大到小排序
        if(t[1] <= k)
        {
            printf("%lld\n", n * k + t[n]);
            continue;
        }
        int fish = 1;//我现在手头有多少鱼
        ll ans = k + sum;//花费的时间
        int tem = n;//现在还剩下多少条鱼
        for(int i = 1; i <= n; i++)
        {
            if(t[i] >= k)//如果这条鱼花费的时间大于等于k
            {
                fish += t[i] / k;
                fish--;
                tem--;
                t[i] %= k;
            }
        }
        if(fish >= tem)//如果不浪费情况下足够我们把鱼做完
        {
            printf("%lld\n", ans);
            continue;
        }
        
        int need = tem - fish;//我还需要多少条鱼
        sort(t + 1, t + 1 + n, cmp);
        int new_n = n;
        for(int i = 1; i <= n; i++)
        {
            if(t[i] == 0)
                new_n--;
        }
        n = new_n;
        for(int i = 1; i <= n; i++)
        {
            t[i] = k - t[i];//把它变成浪费的时间
        }
        sort(t + 1, t + 1 + n);
        for(int i  = 1; i <= need; i++)
        {
            ans += t[i];
        }
        printf("%lld\n", ans);
    }
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值