EOJ:Cleaning Shifts

Cleaning Shifts

Time Limit: 1000MS Memory Limit: 65536K
Total Submits: 75 Accepted: 29

Description

Farmer John's cows, pampered since birth, have reached new heights of fastidiousness. They now require their barn to be immaculate. Farmer John, the most obliging of farmers, has no choice but hire some of the cows to clean the barn. 

Farmer John has N (1 <= N <= 10,000) cows who are willing to do some cleaning. Because dust falls continuously, the cows require that the farm be continuously cleaned during the workday, which runs from second number M to second number E during the day (0 <= M <= E <= 86,399). Note that the total number of seconds during which cleaning is to take place is E-M+1. During any given second M..E, at least one cow must be cleaning. 

Each cow has submitted a job application indicating her willingness to work during a certain interval T1..T2 (where M <= T1 <= T2 <= E) for a certain salary of S (where 0 <= S <= 500,000). Note that a cow who indicated the interval 10..20 would work for 11 seconds, not 10. Farmer John must either accept or reject each individual application; he may NOT ask a cow to work only a fraction of the time it indicated and receive a corresponding fraction of the salary. 

Find a schedule in which every second of the workday is covered by at least one cow and which minimizes the total salary that goes to the cows.

 

Input

Line 1: Three space-separated integers: N, M, and E. 

Lines 2..N+1: Line i+1 describes cow i's schedule with three space-separated integers: T1, T2, and S.

 

Output

Line 1: a single integer that is either the minimum total salary to get the barn cleaned or else -1 if it is impossible to clean the barn.

 

Sample Input

3 0 4
0 2 3
3 4 2
0 0 1

 

Sample Output

5

 

Hint

Explanation of the sample: 
FJ has three cows, and the barn needs to be cleaned from second 0 to second 4. The first cow is willing to work during seconds 0, 1, and 2 for a total salary of 3, etc. Farmer John can hire the first two cows.

 地址:http://202.120.106.94/onlinejudge/problemshow.php?pro_id=131

——————————————————————————————————————————————————————————

现将每头牛按照开始时间为第一关键字,结束时间为第二关键字排序。(其实直接按照结束时间为第一关键字排序也可以)

设DP[I]为从M到I时间雇佣的最小费用,则转移方程DP[I]=MIN(DP[J]+COW[k].W)其中COW[K].A<=J<=COW[K].B,COW[K].A<=I<=COW[K].B。

简单来说:

假设前面所有的牛已经处理好了,即我们已经知道要覆盖M时到X时这么长时间,所需的最小费用DP[I]。

若现在有一头牛P,能从时间COW[P].A工作到COW[P].B,费用为COW[P].W,且COW[P].A<=X<=COW[P].B,那么我们可以用P来更新DP数组。

更新过程如下:

1、先从DP[COW[P].A-1]    {注意:要减1!!!!}  到DP[COW[P].B]中找到一个最小值MIN

2、用MIN+COW[P].W来更新DP[COW[P].A]到DP[COW[P].B]的数据。 

最后的答案即为DP[E]。

现在的问题是怎么求这个最小值MIN及更新DP数组。显然朴素做法要超时……由于只涉及到线段的插入及查询,没有删除,可以用线段树来维护MIN及更新。

DP数组的值直接记录在线段数组里了。

两个程序,本质差不多。

代码
1 //线段树存储了最小值和线段的范围
2  #include<stdio.h>
3 #include<stdlib.h>
4  #define oo 0xffffff
5  #define tree_size 300000
6  #define maxn 10005
7  struct node1
8 {
9 int a,b,w;
10 }cow[maxn];
11  struct node2
12 {
13 int l,r,min;
14 }tree[tree_size];
15  int n,m,e,i,l,r,ans,cost;
16  int max(int a,int b)
17 {
18 if (a>b) return a;
19 return b;
20 }
21  int min(int a,int b)
22 {
23 if (a<b) return a;
24 return b;
25 }
26  int cmp(const void *a,const void *b)
27 {
28 struct node1 *x=(node1 *) a;
29 struct node1 *y=(node1 *) b;
30 if ((x->a)>(y->a)) return 1;
31 else if ((x->a)<(y->a)) return -1;
32 else if ((x->b)>(y->b)) return 1;
33 else return -1;
34 }
35  void build_tree(int l,int r,int num)
36 {
37 int mid;
38 mid=(l+r)/2;
39 tree[num].l=l;
40 tree[num].r=r;
41 tree[num].min=oo;
42 if (l==r) return;
43 build_tree(l,mid,num*2);
44 build_tree(mid+1,r,num*2+1);
45 }
46  void insert(int l,int r,int w,int num)
47 {
48 int mid;
49 mid=(tree[num].l+tree[num].r)/2;
50 if (tree[num].r==tree[num].l)
51 {
52 tree[num].min=min(tree[num].min,w);
53 return;
54 }
55 if (tree[num].l==l&&tree[num].r==r&&w>=tree[num].min) return; //剪枝,如果新的W比当前线段树中的MIN还要大,则没必要更新了。
56   if (mid+1<=l) insert(l,r,w,num*2+1);
57 else if (mid>=r) insert(l,r,w,num*2);
58 else
59 {
60 insert(l,mid,w,num*2);
61 insert(mid+1,r,w,num*2+1);
62 }
63 if (tree[num*2].min==oo||tree[num*2+1].min==oo) //若该段没有被完全覆盖,则最小值没有。(这样写完全是为了上面的那个剪枝)
64   tree[num].min=oo;
65 else
66 tree[num].min=min(tree[num*2].min,tree[num*2+1].min);
67 }
68  int search(int l,int r,int num)
69 {
70 int minl,minr,mid;
71 minl=oo;
72 minr=oo;
73 mid=(tree[num].l+tree[num].r)/2;
74 if (l==tree[num].l&&r==tree[num].r&&tree[num].min<oo)
75 return tree[num].min;
76 if (tree[num].l==tree[num].r)
77 return tree[num].min;
78 if (mid+1<=l)
79 minl=search(l,r,num*2+1);
80 else if (mid>=r)
81 minr=search(l,r,num*2);
82 else
83 {
84 minl=search(l,mid,num*2);
85 minr=search(mid+1,r,num*2+1);
86 }
87 return min(minl,minr);
88 }
89  int main()
90 {
91 scanf("%d%d%d",&n,&m,&e);
92 for (i=0;i<n;i++)
93 scanf("%d%d%d",&cow[i].a,&cow[i].b,&cow[i].w);
94 qsort(cow,n,sizeof(cow[0]),cmp);
95 ans=oo;
96 build_tree(m,e,1);
97 for (i=0;i<n;i++)
98 {
99 if (cow[i].b<m) continue;
100 if (cow[i].a>e) break;
101 l=max(m,cow[i].a);
102 r=min(e,cow[i].b);
103 if (l-1<=m) cost=0;
104 else cost=search(l-1,r,1);
105 if (cost<oo)
106 insert(l,r,cost+cow[i].w,1);
107 }
108 ans=search(e,e,1);
109 if (ans<oo)
110 printf("%d\n",ans);
111 else printf("-1\n");
112 return 0;
113 }
114  
代码
1 //线段树只储存最小值,线段范围在函数的参数给出
2  #include<stdio.h>
3 #include<stdlib.h>
4 #include<memory.h>
5  #define T_size 270000
6  #define maxn 10005
7  struct node
8 {
9 int a,b,w;
10 }cow[maxn];
11  int T[T_size];
12 int n,m,e,i,l,r,ans,cost,oo;
13 int max(int a,int b)
14 {
15 return a>b?a:b;
16 }
17 int min(int a,int b)
18 {
19 return a<b?a:b;
20 }
21 int cmp(const void *a,const void *b)
22 {
23 struct node *x=(node *) a;
24 struct node *y=(node *) b;
25 if ((x->a)>(y->a)) return 1;
26 else if ((x->a)<(y->a)) return -1;
27 else if ((x->b)>(y->b)) return 1;
28 else return -1;
29 }
30 void insert(int st,int en,int l,int r,int w,int ID)
31 {
32 int mid;
33 mid=(st+en)/2;
34 if (st==en)
35 {
36 T[ID]=min(T[ID],w);
37 return;
38 }
39 if (st==l&&en==r&&w>=T[ID]) return;
40 if (mid+1<=l) insert(mid+1,en,l,r,w,ID*2+1);
41 else if (mid>=r) insert(st,mid,l,r,w,ID*2);
42 else
43 {
44 insert(st,mid,l,mid,w,ID*2);
45 insert(mid+1,en,mid+1,r,w,ID*2+1);
46 }
47 if (T[ID*2]==oo||T[ID*2+1]==oo)
48 T[ID]=oo;
49 else
50 T[ID]=min(T[ID*2],T[ID*2+1]);
51 }
52 int search(int st,int en,int l,int r,int ID)
53 {
54 int minl,minr,mid;
55 minl=oo;
56 minr=oo;
57 mid=(st+en)/2;
58 if (l==st&&r==en&&T[ID]<oo)
59 return T[ID];
60 if (st==en)
61 return T[ID];
62 if (mid+1<=l)
63 minl=search(mid+1,en,l,r,ID*2+1);
64 else if (mid>=r)
65 minr=search(st,mid,l,r,ID*2);
66 else
67 {
68 minl=search(st,mid,l,mid,ID*2);
69 minr=search(mid+1,en,mid+1,r,ID*2+1);
70 }
71 return min(minl,minr);
72 }
73 int main()
74 {
75 scanf("%d%d%d",&n,&m,&e);
76 for (i=0;i<n;i++)
77 scanf("%d%d%d",&cow[i].a,&cow[i].b,&cow[i].w);
78 qsort(cow,n,sizeof(cow[0]),cmp);
79 memset(T,0x1f,sizeof(T));
80 oo=T[0];
81 ans=oo;
82 for (i=0;i<n;i++)
83 {
84 if (cow[i].b<m) continue;
85 if (cow[i].a>e) break;
86 l=max(m,cow[i].a);
87 r=min(e,cow[i].b);
88 if (l-1<=m) cost=0;
89 else cost=search(m,e,l-1,r,1);
90 if (cost<oo)
91 insert(m,e,l,r,cost+cow[i].w,1);
92 }
93 ans=search(m,e,e,e,1);
94 if (ans<oo)
95 printf("%d\n",ans);
96 else printf("-1\n");
97 return 0;
98 }
99
posted on 2011-02-05 21:07  风也轻云也淡  阅读(248)  评论(0编辑  收藏  举报