zoukankan      html  css  js  c++  java
  • BZOJ 2034 【2009国家集训队】 最大收益

    Description

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

    Input

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

    Output

    输出最大收益

      这道题一开始想用$KM$算法,然而复杂度不太对……想了半天不会做,去膜了FQW的论文后终于会做了……

      FQW的论文写得很详细,我在这里也没有必要多说什么了……大概思路就是使用贪心的思想来优化特殊二分图的匹配,先找出$n$个有用的点,然后再把任务按收益从大到小排个序,依次$check$能否选当前这个任务……感觉方法实在是很神……

      下面贴代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    #define maxn 5010
    
    using namespace std;
    typedef long long llg;
    
    struct data{
    	int l,r,x;
    }s[maxn];
    int pos[maxn],n,pip[maxn];
    llg ans;
    
    bool cmpl(data a,data b){return a.l<b.l;}
    bool cmpx(data a,data b){return a.x>b.x;}
    bool work(int x,int d){
    	if(pos[d]>s[x].r) return 0;
    	if(!pip[d]){pip[d]=x; return 1;}
    	else
    		if(s[pip[d]].r<s[x].r) return work(x,d+1);
    		else if(work(pip[d],d+1)){pip[d]=x;return 1;}
    		else return 0;
    }
    
    int main(){
    	File("a");
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++) scanf("%d %d %d",&s[i].l,&s[i].r,&s[i].x);
    	sort(s+1,s+n+1,cmpl);
    	for(int i=1;i<=n;i++) pos[i]=max(pos[i-1]+1,s[i].l);
    	for(int i=1,j=1;i<=n;i++){
    		while(pos[j]<s[i].l) j++;
    		s[i].l=j;
    	}
    	sort(s+1,s+n+1,cmpx);
    	for(int i=1;i<=n;i++) if(work(i,s[i].l)) ans+=s[i].x;
    	printf("%lld",ans);
    	return 0;
    }
  • 相关阅读:
    【NOIP2016提高A组集训第14场11.12】随机游走
    poj2378 树形DP
    简单博弈论总结加例题解析
    uva11426 欧拉函数应用
    poj3090欧拉函数求和
    lightOJ1370 欧拉函数性质
    hdu4497 正整数唯一分解定理应用
    hdu1215 正整数唯一分解定理应用
    lightoj 1236 正整数唯一分解定理
    素数筛两种方法
  • 原文地址:https://www.cnblogs.com/lcf-2000/p/6067611.html
Copyright © 2011-2022 走看看