POJ 3171


题目大意:


       给定一个区间范围[M,E],接下来有n行输入。每行输入三个数值:T1,T2,S,表示覆盖区间[T1,T2]


的代价为S,要求你求出覆盖区间[M,E]的最小代价,假设不能覆盖。则输出-1.


解题思路:

 

    先将区间按右端点进行排序,这样我们就能得到dp状态的定义和转移方程:

       dp[i]:表示覆盖[M,cow[i].T2]的最小覆盖代价.

       dp[i] = cow[i].cost (cow[i].l == M) 或者 dp[i] = min(dp[j~i]) + cow[i].cost(cow[j].T2 >= cow[i].T1-1)


因为右端点可能有重合的情况,所以我们的dp[i]中可能存放的并非最小覆盖代价。当然了,


我们能够对右端点进行离散化。然后去重。这样dp数组里面存放的就是最优解。只是这添加了


编程的复杂度,代码量也加大不少.事实上。我们依旧能够用上述dp定义,最后dp[j~i]cow[j].T2==cow[i].T2)


的最小值就能够了.关于dp[i] = min(dp[j~i]) + cow[i].cost,是个RMQ问题,这里我用的是线段树实现的.


以下是解题代码,代码中对空间进行了优化,所以代码中并没有dp数组,其值都存放在线段树中.


#include<stdio.h>
#include<algorithm>
#define MAX_N 11000
#define INF 100000000000
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
struct Node
{
    int l,r,c;
    bool operator < (const Node &tmp) const
    {
        return r < tmp.r;
    }
}cow[MAX_N];
long long tree[MAX_N<<2];
void build(int l,int r,int rt)
{
    tree[rt] = INF ;
    if( l == r)
        return;
    int m = l + ( r - l ) / 2 ;
    build(lson);
    build(rson);
}
long long query(int L,int R,int l,int r,int rt)
{
    if(L <= l && r <= R)
        return tree[rt];
    int m = l + ( r - l ) / 2 ;
    long long tmp = INF;
    if(L <= m)
        tmp = query(L,R,lson);
    if(R > m)
        tmp = min(tmp,query(L,R,rson));
    return tmp;
}
void update(int pos,long long val,int l,int r,int rt)
{
    if(l == r)
    {
        tree[rt] = val ;
        return;
    }
    int m = l + ( r - l ) / 2 ;
    if(pos <= m)
        update(pos,val,lson);
    else
        update(pos,val,rson);
    tree[rt] = min(tree[rt<<1],tree[rt<<1|1]);
}
//去掉不满足条件的区间
int init(int n)
{
    int cnt = 0 , r_max = cow[0].r ;
    for(int i=1;i<n;++i)
    {
        if(cow[i].r != cow[i-1].r)
            r_max = cow[cnt].r ;
        if(cow[i].l - 1 <= r_max)
            cow[++cnt] = cow[i];
    }
    return cnt;
}
int Bin(int key,int l,int r)
{
    while(l <= r)
    {
        int m = l + ( r - l ) / 2 ;
        if(cow[m].r < key)
            l = m + 1 ;
        else
            r = m - 1 ;
    }
    return l;
}
int main()
{
    int n,m,e;
    while(~scanf("%d%d%d",&n,&m,&e))
    {
        int l_min = 90000 , r_max = 0 ;
        for(int i=0;i<n;++i)
        {
            scanf("%d%d%d",&cow[i].l,&cow[i].r,&cow[i].c);
            l_min = min(l_min,cow[i].l);
            r_max = max(r_max,cow[i].r);
        }
        sort(cow,cow+n);
        n = init(n) ;
        if(l_min > m || r_max < e || cow[n].r < e)
        {
            printf("-1\n");
            continue;
        }
        build(0,n,1);
        for(int i=0;i<=n;++i)
        {
            long long tmp;
            if(cow[i].l == m)
                tmp = (long long)cow[i].c ;
            else
                tmp = query(Bin(cow[i].l-1,0,i),i,0,n,1) + cow[i].c;
            update(i,tmp,0,n,1);
        }
        printf("%I64d\n",query(Bin(cow[n].r,0,n),n,0,n,1));
    }
    return 0;
}



posted @ 2018-12-06 12:45  ldxsuanfa  阅读(114)  评论(0编辑  收藏  举报