Alice's mooncake shop
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4122
题意:
Alice开了一家24小时营业的月饼店,2000年1月1日0点是第一个小时,每个整点可以造月饼且造价不同,造的月饼可以当天卖掉或者储存T天(每天每个月饼花费S元),现在Alice有一些订单,求满足这些订单的最少成本。
题解:
先把每天制造一个月饼的成本加上S*( n-i ),然后第 i 天的成本就是[i-T,i]间的最小值减去i*S
代码
#include<stdio.h> #include<string> #include<iostream> using namespace std; const int N=2501; const int M=1e5+1; int mmax(int x,int y) { return x>y?x:y; } long long mmin(long long x,long long y) { return x<y?x:y; } long long dpmin[M][20],need[N],S; bool Leap_Year(int x) { if(x%400==0||(x%4==0&&(x%100!=0)))return true; return false; } int month[13]={0,31,28,31,30,31,30,31,31,30,31,30,31},time[N]; int Find_Time(int y,int m,int d,int h) { int sum=0; for(int i=2000;i<y;++i) { if(Leap_Year(i))sum+=366; else sum+=365; } for(int i=1;i<m;++i) { sum+=month[i]; if(i==2&&Leap_Year(y))sum++; } sum+=(d-1); sum*=24; sum+=h+1; return sum; } long long cost[M]; string s; void Make_Rmq(int m) { for(int i=1;i<=m;++i) { dpmin[i][0]=cost[i]+S*(long long)(m-i); } for(int j=1;(1<<j)<=m;++j) for(int i=1;i+(1<<j)-1<=m;++i) { dpmin[i][j]=mmin(dpmin[i][j-1],dpmin[i+(1<<j-1)][j-1]); } } long long Get_Rmq(int u,int v) { int k=0; while((1<<k+1)<=v-u+1) k++; return mmin(dpmin[u][k],dpmin[v-(1<<k)+1][k]); } void solve() { int n,m,mon,d,y,h,T; while(~scanf("%d%d",&n,&m)&&(n||m)) { for(int i=1;i<=n;++i) { cin>>s; if(s=="Jan")mon=1; else if(s=="Feb")mon=2; else if(s=="Mar")mon=3; else if(s=="Apr")mon=4; else if(s=="May")mon=5; else if(s=="Jun")mon=6; else if(s=="Jul")mon=7; else if(s=="Aug")mon=8; else if(s=="Sep")mon=9; else if(s=="Oct")mon=10; else if(s=="Nov")mon=11; else mon=12; scanf("%d%d%d%lld",&d,&y,&h,&need[i]); time[i]=Find_Time(y,mon,d,h); } scanf("%d%lld",&T,&S); for(int i=1;i<=m;++i) { scanf("%lld",&cost[i]); } Make_Rmq(m); long long res=0; for(int i=1;i<=n;++i) { res+=Get_Rmq(mmax(1,time[i]-T),time[i])*need[i]-(long long)(m-time[i])*S*need[i]; } printf("%lld ",res); } } int main() { solve(); return 0; }