LA 4254 Processor(二分+贪心+优先队列)

这道题目要求找到处理器在执行n个任务时,能完成所有任务的最大速度的最小值。任务有起始时间、结束时间和工作量。通过二分枚举速度,利用优先队列按任务结束时间排序来判断特定速度下任务能否完成。优先级高的任务是结束时间较早的。这种贪心策略确保了最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:有n个任务,每个任务有三个参数ri,di和wi,表示必须在时刻[ri,di]之内执行,工作量为wi。处理器执行速度可以变化,当执行速度为s时,工作量为wi。处理器的速度可以变化,当执行速度为s时,一个工作量为wi的任务需要执行wi/s个单位时间。任务不一定连续执行,可以分成若干块。求出处理器执行过程中最大速度的最小值。


其实刚看到这道题的时候,看到最大值的最小值,首先想到要用二分枚举答案,而且这个想法也十分正确。

但是问题的难点在于如何判断在某个速度下能否完成所有任务,所以必然要有个优先级,什么样的任务应该先做。可以发现如果现在可以选择执行的任务有多个,那么必然要选择结束时间早的任务先执行,这样才能获得最优解。

所以总体的思路就是,将所有任务按照开始时间排序,二分枚举处理器的速度,然后对每个速度进行判断。按照任务开始时间依次加入优先队列,队列优先级是结束时间早的优先。最后就能判断该速度是否能够执行完所有任务。

#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <queue>
#define INF 0x7fffffff
using namespace std;
struct node
{
    int l,r,v;
} p[2000005],u;
bool operator < (node a,node b)
{
    return a.r>b.r;
}
int cmp(node a ,node b)
{
    return a.l<b.l;
}
int n,L,R,sum;

bool check(int x)
{
    int i,t,k=0;
    priority_queue<node> Q;
    for(i=L; i<=R; i++)
    {
        t=x;
        while(k!=n&&p[k].l<i) Q.push(p[k++]);
        while(!Q.empty()&&t!=0)
        {
            u=Q.top();
            Q.pop();
            if(u.r<i) return false ;
            if(u.v>t)
            {
                u.v-=t;
                t=0;
                Q.push(u);
            }
            else t-=u.v;
        }
    }
    if(Q.empty()) return true;
    else return false;
}
int main()
{
    int T;
    int i,j;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(i=0,sum=0,L=INF,R=0; i<n; i++)
        {
            scanf("%d%d%d",&p[i].l, &p[i].r, &p[i].v);
            R=max(R,p[i].r);
            L=min(L,p[i].l);
            sum+=p[i].v;
        }
        sort(p,p+n,cmp);
        int ans=INF; 
        int l,r,mid;
        l=1,r=sum;
        while(l<=r)
        {
            mid=(l+r)>>1;
            if(check(mid))
            {
                r=mid-1;
                ans=min(ans,mid);
            }
            else l=mid+1;
        }
        printf("%d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值