HDU 4122 POJ 4002 Alice's mooncake shop(单调队列)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4122

         http://poj.org/problem?id=4002

题意:一个生产月饼的工厂,给出一个数m,该工厂只在前m小时(也就是[1,m])生产月饼。给出一系列订单,订单给出在第i小时买家要拿走R数量的月饼(1<=i<=m)。生产一个月饼的单价每天不同。工厂有一个冰箱,可以将提前生产的月饼放在冰箱里(工厂也可以在订单到来的那个时刻生产,生产月饼可以瞬间完成),但是放在冰箱里的时间不能超过T。每个月饼在冰箱里保存一天需要额外的费用S。制定工厂的生产计划使得总花费最少?冰箱无限大,每小时生产月饼数量没有限制。

思路:对于每个订单,设其到来时间为x,其实我们只要知道从x向前长度为T的区间之内,即[x-T,x],最小代价的是多少即可。另外,对于某个时间x1以及之前的一个时间x0,若p[x0]+(x1-x0)*S>=p[x1](p[i]表示时间i生产一个月饼的花费),则x0这个记录就不再需要记录,因为以后至少x1会比x0好。基于这样的事实,可以使用单调队列。

 


 
 
 struct node
 {
     char s[10];
     int day,year,H,R;
 
     void get()
     {
         scanf("%s%d%d%d%d",s,&day,&year,&H,&R);
     }
 };
 
 const int MAX=100005;
 node b[2505];
 int n,m,S,T,p[MAX],t[2505];
 
 
 char map[12][10]={"Jan","Feb","Mar","Apr",
                   "May","Jun","Jul","Aug",
                   "Sep","Oct","Nov","Dec"};
 int M[2][13]={
  {0,31,28,31,30,31,30,31,31,30,31,30,31},
  {0,31,29,31,30,31,30,31,31,30,31,30,31}
 };
 
 int Y[]={365,366};
 
 int getMonth(char s[])
 {
     int i;
     for(i=0;i<12;i++) if(strcmp(map[i],s)==0) break;
     return i+1;
 }
 
 int OK(int x)
 {
     return x%400==0||x%100&&x%4==0;
 }
 
 int cal(node a)
 {
     int year=a.year;
     int month=getMonth(a.s);
     int day=a.day;
     int ans=0,t,i;
     for(i=2000;i=p[i])
                 tail--;
             Q[tail].x=p[i];
             Q[tail].y=i;
             tail++;
             while(j<=n&&t[j]==i)
             {
                 while(head

 

  

 

 

你可能感兴趣的:(HDU 4122 POJ 4002 Alice's mooncake shop(单调队列))