果园守望者
来源:互联网 发布:恒生交易软件 编辑:程序博客网 时间:2024/05/11 06:22
Description
重庆有很多区县都盛产水果,每当到了水果成熟的时节,何老板就会看准商机,推出了一项名为“果园守望者”的服务。该服务很简单,就是何老板安排人手去为你看守果园,帮你驱赶鸟兽或者小偷。
最近,何老板又签下了一个看守合同,该合同需要何老板派人看守一个果园,时间是从第A天起一直到第B天。在这B-A+1天里,要求每天至少有一个人在看守果园。
何老板手下共有N个员工。每个员工都对自己的工作时间和报酬有一定的要求,比如员工甲只在T1..T2这段时间工作,并要求S1元的报酬;员工乙只在T3..T4这段时间工作,并要求S2元的报酬......
请你帮助何老板安排一个工作时间表,使得从第A天到第B天每天至少有一个员工在看守果园,并且使得何老板支付的报酬总数尽可能少。
Input
第一行,三个空格间隔的整数N,A,B
接下来N行,每行三个整数T1,T2,和S,表示对应员工愿意工作的起止时间和要求的报酬。
Output
一个整数,表示何老板需支付的最少报酬总数。如果无法安排员工完成工作,输出-1
Sample Input
3 0 40 2 33 4 20 0 1
Sample Output
5
Hint
1 <= N <= 10,000
0 <= A <= B <= 90000
A <= T1 <= T2 <= B
0 <= S <= 500,000
样例说明
安排第一个员工工作0,1,2三天
安排第二个员工工作3,4两天
就把从第0天到第4天这5天的看守工作完成了。
【分析】
这道题明显是DP。定义状态数组:F[i]表示以i天结尾的最优值。
如果是不能交叉的覆盖,那么方程为F[T[i].b]=min(F[k])+T[i].w k<=T[i].a-1;
但是题目的意思是可以有覆盖的,那么只需要修改边界条件为 T[i].a-1<=k<=T[i].b (因为要完全覆盖,所以有下界)。
修正后的方程:F[i]=min(F[k])+T[j].w (i=T[j].b,T[j].a-1<=k<=T[j].b)。但是这样的话复杂度就会很高O(N*B),所以可以用线段树优化。即多加一个域dp来维护动归过程。(我的线段树是堆式线段树,代码有体现)
【代码】
#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<ctime>#include<iostream>#include<algorithm>using namespace std;const int INF=1000000000;int N,A,B;struct wjj{int a,b,w;}T[10005];struct node{int L,R,dp;}Tree[400005];bool _cmp(wjj x,wjj y){return (x.a<y.a);}void _built(int id,int l,int r){int mid;Tree[id].L=l;Tree[id].R=r;Tree[id].dp=INF;if(l<r){mid=(l+r)>>1;_built((id<<1),l,mid);_built((id<<1)+1,mid+1,r);}}void _insert(int id,int r,int v){if(Tree[id].L==Tree[id].R) Tree[id].dp=min(Tree[id].dp,v);else{int mid=(Tree[id].L+Tree[id].R)>>1;if(r<=mid) _insert((id<<1),r,v);else _insert((id<<1)+1,r,v);Tree[id].dp=min(Tree[id].dp,min(Tree[(id<<1)].dp,Tree[(id<<1)+1].dp));}}int _findans(int id,int l,int r){if(l<=Tree[id].L&&Tree[id].R<=r) return Tree[id].dp;int mid=(Tree[id].L+Tree[id].R)>>1;int temp=INF;if(l<=mid) temp=min(temp,_findans((id<<1),l,r));if(mid<r) temp=min(temp,_findans((id<<1)+1,l,r));return temp;}void _init(){scanf("%d%d%d",&N,&A,&B);for(int i=1;i<=N;i++) scanf("%d%d%d",&T[i].a,&T[i].b,&T[i].w);sort(T+1,T+1+N,_cmp); //按工作开始时间由小到大排序 }void _solve(){int temp,ans;_built(1,A,B);_insert(1,A-1,0); //初始化线段树,把A之前的时间所需费用初始化为0 for(int i=1;i<=N;i++){temp=_findans(1,T[i].a-1,T[i].b);_insert(1,T[i].b,temp+T[i].w);}ans=_findans(1,B,B);if(ans==INF) printf("-1\n");else printf("%d\n",ans);}int main(){_init();_solve();return 0;}
- 果园守望者
- 守望者
- 守望者
- 时间守望者1.1
- WATCHMEN 守望者,好看。
- 迷茫中的守望者
- 守望者的贪心
- 守望者的逃离
- 守望者的逃离
- 守望者的逃离
- - 麦田守望者 -读后感
- 城市的守望者
- 守望者的逃离
- 守望者的逃离
- 守望者的逃离
- 守望者的逃离
- 守望者的逃离
- 守望者的逃离
- WIN32 API编程,wParam lParam参数小结
- 字符串指针与字符数组的区别
- ios 手势 事件 全
- 单元测试代码生成器
- Struts.xml配置详解
- 果园守望者
- 从B树、B+树、B*树谈到R 树
- android+NDK环境搭建遇到的问题
- 卷积的意义
- 这几天笔面试题目总结
- Android 如何在关于手机界面添加个图片
- Visual C++ 中 的ODBC 编 程
- 关闭子窗口后,刷新父窗口。
- 博 藏