zoukankan      html  css  js  c++  java
  • 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
    ");
                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
    ",query(Bin(cow[n].r,0,n),n,0,n,1));
        }
        return 0;
    }
    



  • 相关阅读:
    VS2010自定义新建文件模版 狼人:
    理解“.NET技术”.NET程序集的执行过程 狼人:
    JAVA与.NET的相互调用——利用JNBridge桥接模式实现远程通讯 狼人:
    《Effective C#中文版:改善C#程序的50种方法》读书笔记 狼人:
    C#中“.NET技术”字符串的内存分配与驻留池 狼人:
    ASP.NET MVC 3和Razor中的@helper 语法 狼人:
    用C#实现HTTP协“.NET技术”议下的多线程文件传输 狼人:
    JA“.NET技术”VA与.NET的相互调用——TCP/IP相互调用基本架构 狼人:
    《Effective C#中文版:改善C#程序的50种方法》“.NET技术”读书笔记 狼人:
    C#“.NET技术” 中奇妙的函数联接序列的五种简单方法 狼人:
  • 原文地址:https://www.cnblogs.com/ldxsuanfa/p/10076087.html
Copyright © 2011-2022 走看看