poj 3616 Milking Time(DP)

传送门

https://www.cnblogs.com/violet-acmer/p/9852294.html

 

题意:

  John有个喝奶的列表,共M个喝奶信息,每个喝奶信息都有个开始时间,结束时间和此次喝奶的量。

  当John在区间[a,b]喝完奶后,需要休息R时,即下一次喝奶最少要在 b+R 后。

  问John最多和多少奶?

题解:

  相关变量啊解释:

 1 int N,M,R;
 2 struct Node
 3 {
 4     int start,end;
 5     int drink;//喝奶量
 6     Node(int a=0,int b=0,int c=0){
 7         start=a,end=b,drink=c;
 8     }
 9 }List[maxn];
10 int dp[(int)1e6+10];//dp[i]:第i时喝奶的最大值
11 int maxDrink;//当前喝奶的最大值

  步骤:

    (1):将List[ ]按照 start 由小到大排序;

    (2):从后往前遍历,根据dp[ ]的定义,可得状态转移方程为

      dp[ i ]=max( maxDrink,List[ i ].drink + dp[ nextStart ] );

      maxDrink : 由 M 到 i 的遍历中最大的喝奶量。

      nextStart : 距当前喝奶结束时刻之后的R时刻最近的开始时刻,即喝奶时刻 >= List[ i ].end + R 的最近的时刻。

    (3):遍历完后,输出dp[ List[1].start ];

AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 #define mem(a,b) memset(a,b,sizeof(a))
 7 const int maxn=1e3+10;
 8 
 9 int N,M,R;
10 struct Node
11 {
12     int start,end;
13     int drink;//喝奶量
14     Node(int a=0,int b=0,int c=0){
15         start=a,end=b,drink=c;
16     }
17 }List[maxn];
18 int dp[(int)1e6+10];//dp[i]:第i时喝奶的最大值
19 int maxDrink;//当前喝奶的最大值
20 
21 bool cmp(Node _a,Node _b){
22     return _a.start < _b.start;
23 }
24 
25 int binarySearch(int x)
26 {
27     int l=0,r=M+1;
28     while(r-l > 1)
29     {
30         int mid=l+((r-l)>>1);
31         if(List[mid].start >= x)
32             r=mid;
33         else
34             l=mid;
35     }
36     return r;
37 }
38 void updataDp(int i)
39 {
40     int nextStart=List[i].end+R;//下一喝奶时刻至少是 nextStart
41     int t=binarySearch(nextStart);//查找距离i最近的喝奶开始时刻 >= nextStart 的喝奶编号
42     if(t == M+1)//如果 t == M+1,说明 nextStart 之后没有喝奶开始时刻
43     {
44         maxDrink=max(maxDrink,List[i].drink);//更新maxDrink
45         dp[List[i].start]=maxDrink;//更新dp[]
46         return ;
47     }
48     nextStart=List[t].start;//如果找到下一喝奶开始时刻
49     maxDrink=max(maxDrink,List[i].drink+dp[nextStart]);
50     dp[List[i].start]=maxDrink;
51 }
52 int Solve()
53 {
54     sort(List+1,List+M+1,cmp);
55     mem(dp,0);
56     maxDrink=0;
57     for(int i=M;i > 0;--i)//从后往前遍历
58         updataDp(i);//更新dp[]
59     return dp[List[1].start];
60 }
61 int main()
62 {
63     scanf("%d%d%d",&N,&M,&R);
64     for(int i=1;i <= M;++i)
65     {
66         int a,b,c;
67         scanf("%d%d%d",&a,&b,&c);
68         List[i]=Node(a,b,c);
69     }
70     printf("%d\n",Solve());
71 }
View Code

  空间分析:

    本来以为会MLE的.........

    

    dp[]数组浪费了好多空间,其实可以只开 1000 大小的,刚开始思路有点混乱,再加上需要复习专业课,然后,就不太像优化了,直接开了 1e6 的数组,竟然过了......

    考完后一定要优化一下。

posted @ 2018-12-04 21:10  HHHyacinth  阅读(159)  评论(0编辑  收藏  举报