NYOJ 720 DP+二分

2021年09月15日 阅读数:1
这篇文章主要向大家介绍NYOJ 720 DP+二分,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

项目安排

时间限制: 3000 ms  |  内存限制:65535 KB
难度: 4
描述
小明天天都在开源社区上作项目,假设天天他都有不少项目能够选,其中每一个项目都有一个开始时间和截止时间,假设作完每一个项目后,拿到报酬都是不一样的。因为小明立刻就要硕士毕业了,面临着买房、买车、给女朋友买各类包包的鸭梨,可是他的钱包却空空如也,他须要足够的money来充实钱包。万能的网友麻烦你来帮帮小明,如何在最短期内安排本身手中的项目才能保证赚钱最多(注意:作项目的时候,项目不能并行,即两个项目之间不能有时间重叠,可是一个项目刚结束,就能够当即作另外一个项目,即项目起止时间点能够重叠)。
输入
输入可能包含多个测试样例。
对于每一个测试案例,输入的第一行是一个整数n(1<=n<=5000):表明小明手中的项目个数。
接下来共有n行,每行有3个整数st、ed、val,分别表示项目的开始、截至时间和项目的报酬,相邻两数之间用空格隔开。
st、ed、value取值均在32位有符号整数(int)的范围内,输入数据保证全部数据的value总和也在int范围内。
输出
对应每一个测试案例,输出小明能够得到的最大报酬。
样例输入
3
1 3 6
4 8 9
2 5 16
4
1 14 10
5 20 15
15 20 8
18 22 12
样例输出
16
22
提示
上传时数据增强,项目起始时间和终止时间可能相同(其余oj可能无此状况)
来源
网易有道2013年校园招聘面试二面试题
上传者
勿念情
感受N^2也能够过啊,T了,后来用的二分A掉,二分写炸了调了半天最后发现排序小标写错了,ccc
dp[i]表示前i个项目可得到的最大价值,则dp[i]=max(dp[i-1],solve(i-1)+P[i].val)
solve()就是咱们要找的在知足与目标项目不交叉的状况下的最大价值。
因为要二分查找显然dp[]数组必须有序,因此dp[i]表示前i个项目可得到的最大价值,这样的话二分找到的某个合法项目以前的项目显然也在目标项目以前且不交叉。
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f;
struct node
{
    int st,ed,val;
    bool operator<(const node &c)const{
    if(st==c.st&&ed==c.ed) return val>c.val;
    if(ed==c.ed) return st<c.st;
    return ed<c.ed;
    }
}P[5005];
int dp[5005];
int solve(int t)
{
    if(!t) return 0;
    int l=1,r=t,mid,i,j,k,ans=0;
    while(l<r){
        mid=r-(r-l)/2;
        if(P[mid].ed<=P[t+1].st){
          l=mid;
        }
        else{
          r=mid-1;
        }
    }
    if(l==r&&P[l].ed<=P[t+1].st) return dp[l];
    return 0;

}
int main()
{
    int N,i,j,k;
    node a,b;
    while(cin>>N){
        for(i=1;i<=N;++i){
            scanf("%d%d%d",&P[i].st,&P[i].ed,&P[i].val);
        }
        sort(P+1,P+N+1);
    for(i=1;i<=N;++i){
        dp[i]=max(solve(i-1)+P[i].val,dp[i-1]);
    }
    printf("%d\n",dp[N]);
    }
    return 0;
}