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<year;i++) ans+=Y[OK(i)];

     t=OK(year);

     for(i=1;i<month;i++) ans+=M[t][i];

     ans+=day-1;

     return ans*24+a.H+1;

 }

 

 struct Node

 {

     int x,y;

 };

 

 Node Q[MAX];

 int head,tail;

 

 int main()

 {

     while(scanf("%d%d",&n,&m),n||m)

     {

         int i;

         for(i=1;i<=n;i++) b[i].get(),t[i]=cal(b[i]);

         scanf("%d%d",&T,&S);

         for(i=1;i<=m;i++) scanf("%d",&p[i]);

         __int64 ans=0;

         int j=1;

         head=tail=0;

         for(i=1;i<=m;i++)

         {

             while(head<tail&&Q[tail-1].x+(i-Q[tail-1].y)*S>=p[i])

                 tail--;

             Q[tail].x=p[i];

             Q[tail].y=i;

             tail++;

             while(j<=n&&t[j]==i)

             {

                 while(head<tail&&Q[head].y+T<i) head++;

                 ans+=((__int64)(Q[head].x+(i-Q[head].y)*S))*b[j].R;

                 j++;

             }

         }

         printf("%I64d\n",ans);

     }

     return 0;

 }

 

  

 

 

你可能感兴趣的:(poj)