题意:月饼商店从2000年1月1日0时开始开m个小时,只能在整点的时候才能做月饼,给出每个时间点做一个月饼的费用,做月饼的时间不计,有n个订单,取货的日期和数量,商店有冷藏库,容量无限大,月饼的冷藏时间有限,冷藏是要花钱的,求出这n个订单总共最少得花多少钱。
思路:对于每个订单ti都是在ti-t—ti时间段内找出做月饼花费最小时间点,可以先求出任意时间点做月饼满足最后一个订单的费用(不考虑冷藏时限),然后用线段树处理区间最小值,然后对于每个订单找出ti-t—ti区间的最小值,然后要减去该订单的时间到最后订单时间的冷藏费用。ti-t可能小于0,ti可能大于m。
#include<stdio.h> #include<string.h> const int N=100100; int time[N],n,aa[N]; char ss[15][10]= {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; int days[15]= {31,28,31,30,31,30,31,31,30,31,30,31}; struct date { int year,month,day,hour,cont; }mark[N]; int min(int a,int b) { if(a>b)return b; return a; } int leap(int year) { return (year%4==0&&year%100!=0)||year%400==0; } int tianshu(date a)//求天数 { int ret=a.year*365+(a.year-1)/4-(a.year-1)/100+(a.year-1)/400,i; days[1]+=leap(a.year); for(i=0; i<a.month-1; ret+=days[i++]); days[1]=28; return ret+a.day; } int hanshu(date a,date b)//求小时 { int rest=tianshu(a)-tianshu(b); rest*=24; if(b.hour<a.hour) rest+=(a.hour-b.hour); else rest-=(b.hour-a.hour); return rest+b.hour; } void Time() { int i,j; char str[10]; for(i=1; i<=n; i++) { scanf("%s%d%d%d%d",str,&mark[i].day,&mark[i].year,&mark[i].hour,&mark[i].cont); for(j=0;j<12; j++) { if(strcmp(str,ss[j])==0) { mark[i].month=j+1; break; } } } mark[0].year=2000; mark[0].month=1; mark[0].day=1;mark[0].hour=0; for(i=1; i<=n; i++) time[i]=hanshu(mark[i],mark[0]);//订单的时间 } struct Tree { int L,R,mw; }T[N*5]; void buildTree(int L,int R,int id) { T[id].L=L;T[id].R=R; if(L==R) { T[id].mw=aa[L]; return ; } int mid=(L+R)>>1,li=id<<1,ri=li|1; buildTree(L,mid,li); buildTree(mid+1,R,ri); T[id].mw=min(T[li].mw,T[ri].mw); } int find(int L,int R,int id) { if(T[id].L==L&&T[id].R==R) return T[id].mw; int mid=(T[id].L+T[id].R)>>1,li=id<<1,ri=li|1; if(R<=mid) return find(L,R,li); else if(L>mid) return find(L,R,ri); else return min(find(L,mid,li),find(mid+1,R,ri)); } int main() { int m,i,tt,s; __int64 temp,ans; while (scanf("%d%d",&n,&m)!=EOF) { if (n==0 && m==0) break; memset(time,0,sizeof(time)); Time(); scanf("%d%d",&tt,&s); for(i=0;i<m;i++) { scanf("%d",&aa[i]); if(i<=time[n]) aa[i]+=((time[n]-i)*s); } buildTree(0,time[n],1); ans=0; for(i=1;i<=n;i++) { if(time[i]-tt<0) temp=find(0,min(m-1,time[i]),1); else temp=find(time[i]-tt,min(m-1,time[i]),1); temp-=((time[n]-time[i])*s); ans+=(temp*mark[i].cont); } printf("%I64d\n",ans); } return 0; }