POJ 3616【数状数组求区间最大值 + 简单DP】

题目:Milking Time

题意:

给出一个数N,表示Bessie在0~N时间段进行挤牛奶工作。然后给出M行数值,每一行为f,t,v,分别表示在时间断f,t内Bessie能挤到的牛奶量。然后给出一个R,表示每次Bessie挤完牛奶都要休息R小时才能继续下一个工作,求Bessie最大的挤奶量。

解题思路:

很简单的DP,刚开始WA了两次,因为时间两边的界限没处理好。转移式:DP[i] = max{DP[D[j].to], DP[D[j].from - R] + D[j].val},要求某一区间的最大值,可以用数状数组实现。

View Code
 1 #include <iostream>
2 #include <cstdio>
3 #include <string>
4 #include <cstring>
5 #include <algorithm>
6 #include <vector>
7 #include <map>
8
9 using namespace std;
10 const int MAXN = 1000000 + 10;
11 const int MAXM = 1000 + 10;
12
13 struct T
14 {
15 int from, to, val;
16 }D[MAXM];
17
18 bool comp(const T& a, const T& b)
19 {
20 return a.to < b.to;
21 }
22 inline int getMax(int a, int b)
23 {
24 return a < b ? b : a;
25 }
26 inline int getMin(int a, int b)
27 {
28 return a < b ? a : b;
29 }
30 int N, M, R;
31 int G[MAXN];
32 int C[MAXN];
33
34 int lowBit( int k )
35 {
36 return k & (k^(k-1));
37 }
38 int getRes( int end )
39 {
40 int sum=0;
41 while( end>0 )
42 {
43 sum = getMax(sum, C[end]);
44 end-=lowBit(end);
45 }
46 return sum;
47 }
48 void add( int k, int val)
49 {
50 while( k<=N )
51 {
52 C[k] = getMax(C[k], val);
53 k+=lowBit(k);
54 }
55 }
56
57 int main()
58 {
59 //freopen("in.txt","r",stdin);
60 scanf("%d%d%d", &N, &M, &R);
61 for(int i = 0; i < M; ++i)
62 {
63 scanf("%d%d%d", &D[i].from, &D[i].to, &D[i].val);
64 }
65 sort(D, D + M, comp);
66 int lowMax = 0;
67 int max = 0;
68 for(int i = 0; i < M; ++i)
69 {
70 max = getRes(D[i].to);
71 lowMax = getRes(D[i].from - R);
72 if(lowMax + D[i].val > max)
73 {
74 add(D[i].to, lowMax + D[i].val);
75 }
76 }
77 printf("%d\n", getRes(N));
78 return 0;
79 }



你可能感兴趣的:(poj)