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 }
空间分析:
本来以为会MLE的.........
dp[]数组浪费了好多空间,其实可以只开 1000 大小的,刚开始思路有点混乱,再加上需要复习专业课,然后,就不太像优化了,直接开了 1e6 的数组,竟然过了......
考完后一定要优化一下。