POJ 3171

来源:互联网 发布:c 调用c dll 源码 编辑:程序博客网 时间:2024/06/05 09:19


题目大意:


       给定一个区间范围[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|1using 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;}



0 0
原创粉丝点击