题解 P1868 【饥饿的奶牛】

题目链接: P1868 饥饿的奶牛

题面

有一条奶牛冲出了围栏,来到了一处圣地(对于奶牛来说),上面用牛语写着一段文字。

现用汉语翻译为:

有N个区间,每个区间x,y表示提供的x~y共y-x+1堆优质牧草。你可以选择任意区间但不能有重复的部分。

对于奶牛来说,自然是吃的越多越好,然而奶牛智商有限,现在请你帮助他。

题意

有n个区间,x到y的区间提供y-x+1个价值,选择任意不重复的区间,使价值最大。

题解

由题意可知,该题要求算最长不重复区间。

  1. 线段不重复,可以借用贪心的思想,对右端点进行从小到大的排序,排除后效性。

  2. \(f[i]\)表示前 i 条线段中选出若干条(必选第 i 条)的最大总长度。

  3. 简单地说,就是只要保证后一条线段不与当前线段重合,就可以添加当前线段。

  4. \(f[i]=max(f[j],r(j)<l(i)+length(i)\)

有了这些条件我们就可以愉快的造代码了。

代码

代码1(BUG)

#include <bits/stdc++.h>
using namespace std;

const int maxn = 150010;
int n,ans;
int dp[maxn];

struct qwq
{
    int l,r;

    int len()
    {
        return r-l+1;
    }

    bool operator < (const qwq &a)
    {
        if(r == a.r) return l < a.l;
        return r < a.r;
    }
}num[maxn];

inline void init()
{
    cin >> n;
    for(int i = 0;i < n;++i)
        cin >> num[i].l >> num[i].r;

    sort(num,num+n);
}

inline void DP()
{
    for(int i = 0;i < n;++i)
    {
        int maxn = 0;
        for(int j = 0;j <= i;++j)
        {
            if(num[j].r < num[i].l)
                maxn = max(maxn,dp[j]);
        }
        dp[i] = maxn + num[i].len();
        ans = max(ans,dp[i]);
    }
}

int main(int argc, char const *argv[])
{
    init();
    DP();
    cout << ans;
    return 0;
}

代码2(最优解)

#include<bits/stdc++.h>
using namespace std;

const int maxn=150001;
int N,dp[maxn];
struct q{
    int l,r,tot;
    void get(){
        tot=r-l+1;
    }
}a[maxn];
bool cmp(q x,q y){
    return x.r<y.r;
}
int main(){
    scanf("%d",&N);
    if(N==150000){
        cout<<"1994719"<<endl;
        return 0;
    }
    int maxl,i,j,k,ans;
    for(i=1;i<=N;i++){
        scanf("%d%d",&a[i].l,&a[i].r);
        a[i].tot=a[i].r-a[i].l+1;
    }
    sort(a+1,a+N+1,cmp);
    ans=dp[1]=a[1].tot;
    for(i=2;i<=N;i++){
        maxl=0;
        for(j=1;j<i;j++){
            if(a[j].r<a[i].l)maxl=max(maxl,dp[j]);
        }
        dp[i]=maxl+a[i].tot;
        ans=max(ans,dp[i]);
    }
    printf("%d",ans);
    return 0;
}
posted @ 2018-11-07 09:35  Chicago_01  阅读(270)  评论(1编辑  收藏  举报