• 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
    ",Solve());
    71 }
    View Code

      空间分析:

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

        

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

        考完后一定要优化一下。

  • 相关阅读:
    bzoj1914
    bzoj3144
    bzoj2756
    poj3177
    一些比较水的题目
    bzoj2282
    屯题50AC纪念
    Base64解码中文部分中文乱码的原因
    随机生成36位字符串
    jQuery判断某个元素是否存在某个样式
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/10066899.html
Copyright © 2020-2023  润新知