BZOJ2034最大收益 [贪心优化特殊图最优匹配]

2034: [2009国家集训队]最大收益

Time Limit: 10 Sec   Memory Limit: 259 MB
Submit: 498   Solved: 209
[ Submit][ Status][ Discuss]

Description

给出N件单位时间任务,对于第i件任务,如果要完成该任务,需要占用[Si, Ti]间的某个时刻,且完成后会有Vi的收益。求最大收益。 N≤5000,1 ≤ Si ≤ Ti ≤ 108,1 ≤ Vi ≤ 108。 澄清:一个时刻只能做一件任务,做一个任务也只需要一个时刻。

Input

第一行一个整数N,表示可供选择的任务个数. 接下来的第二到第N+1行,每行三个数,其中第i+1行依次为Si,Ti,Vi

Output

输出最大收益

Sample Input

4
1 1 2
2 2 2
1 2 3
1 3 1

Sample Output

6

HINT

共有四个任务,其中第一个任务只能在时刻1完成,第二个任务只能在时刻2做,第三个任务只能在时刻1或时刻2做,第四个任务可以在[1,3]内任一时刻完成,四个任务的价值分别为2、2、3和1。一种完成方案是:时刻1完成第一个任务,时刻2完成第三个任务,时刻3完成第四个任务,这样得到的总收益为2+3+1=6,为最大值。


分析:直接看论文

#include<bits/stdc++.h>
using namespace std;
#define N 5005
#define LL long long
struct node
{
    int x, y, z, s;
}a[N];
int n, match[N], pos[N];
bool cmp1(const node &u, const node &v){return u.x < v.x;}
bool cmp2(const node &u, const node &v){return u.z > v.z;}
bool check(int k, int x)
{
    if(pos[x]>a[k].y) return false;
    if(!match[x])
    {
        match[x] = k;
        return true;
    }
    else if(a[match[x]].y < a[k].y) return check(k, x+1);
    else if(check(match[x], x+1))
    {
        match[x]=k;
        return true;
    }
    else
        return false;
}
int main()
{
    scanf("%d", &n);int i;
    for(i=1; i<=n; i++) scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].z);
    sort(a+1, a+n+1, cmp1);
    for(i=1; i<=n; i++) pos[i]=max(pos[i-1]+1, a[i].x);
    for(i=2, a[1].s=1; i<=n; i++)
    {
        a[i].s=a[i-1].s;
        while(pos[a[i].s]<a[i].x&&a[i].s<n) a[i].s++;
    }
    sort(a+1, a+n+1, cmp2);
    LL ans=0;
    for(i=1; i<=n; i++) if(check(i, a[i].s)) ans+=a[i].z;
    printf("%lld\n", ans);
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值