【gmoj】【二分图】最大收益
题目
解题思路
可以定义每个任务的活跃点,也就是做完前i个任务,且大于第i个任务时间左边界的时间点
按时间左边界从小到大排序,求出活跃点
然后按权值排序从大到小,任务匹配活跃点,类似二分图
代码
#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
struct lzf{
int l,r,q;
}b[5010];
long long ans;
int n,l,r,q,pos[5010],ins[5000010];
bool cmp(lzf l,lzf y)
{
return l.l<y.l;
}
bool cmp2(lzf l,lzf y)
{
return l.q>y.q;
}
bool check(int x,int y)
{
if (pos[y]>b[x].r) return false;
if (ins[y]==0)
{
ins[y]=x;
return true;
}
if (b[x].r<b[ins[y]].r)
{
if (check(ins[y],y+1))
{
ins[y]=x;
return true;
}
}
else if (check(x,y+1)) return true;
return false;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d%d%d",&l,&r,&q);
b[i]=(lzf){l,r,q};
}
sort(b+1,b+n+1,cmp);
int j=0;
for (int i=1;i<=n;i++)
{
j=max(j,b[i].l);
pos[i]=j;
j++;
}
sort(b+1,b+n+1,cmp2);
for (int i=1;i<=n;i++)
{
int j=1;
while (pos[j]<b[i].l) j++;
if (check(i,j)) ans+=b[i].q;
}
printf("%lld",ans);
return 0;
}