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
- POJ 3171
- POJ-3171-Cleaning Shifts
- poj 3171 rmq+dp
- poj 3171 Cleaning Shifts
- poj 3171 Cleaning Shifts
- POJ
- poj
- POJ
- POJ
- poj
- poj
- POJ
- POJ
- poj
- POJ
- POJ
- POJ
- POJ
- Broadcast receiver 动态注册 & 作为内部类接收广播 详解
- scikit-learn安装
- 双硬盘安装ubuntu的一点心得
- Web应用中页面跳转的路径问题
- MFC给主程序添加滚动条!
- POJ 3171
- 切纸术(动归)——锯钢条二维版
- Linux内核之vmlinux与vmlinuz
- 使用PHP调用微信API,使用微信做通知类应用的方法
- Delphi学习笔记三 运算符
- 转载的一篇IE之haslayout
- 【Leetcode】TwoSum
- IOS网络编程
- LINUX下的用户访问授权,文件权限