HDU 4122 Alice's mooncake shop(RMQ:动态最值)

HDU 4122 Alice's mooncake shop(RMQ:动态最值)

http://acm.hdu.edu.cn/showproblem.php?pid=4122

题意:

        Alice has opened up a 24-hour mooncake shop. She always gets a lot of orders. Only when the time is K o’clock sharp( K = 0,1,2 …. 23) she can make mooncakes, and We assume that making cakes takes no time. Due to the fluctuation of the price of the ingredients, the cost of a mooncake varies from hour to hour. She can make mooncakes when the order comes,or she can make mooncakes earlier than needed and store them in a fridge. The cost to store a mooncake for an hour is S and the storage life of a mooncake is T hours. She now asks you for help to work out a plan to minimize the cost to fulfill the orders.

Input
The input contains no more than 10 test cases. 
For each test case:
The first line includes two integers N and M. N is the total number of orders. M is the number of hours the shop opens. 
The next N lines describe all the orders. Each line is in the following format:

month date year H R

It means that on a certain date, a customer orders R mooncakes at H o’clock. “month” is in the format of abbreviation, so it could be "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov" or "Dec". H and R are all integers. 
All the orders are sorted by the time in increasing order. 
The next line contains T and S meaning that the storage life of a mooncake is T hours and the cost to store a mooncake for an hour is S.
Finally, M lines follow. Among those M lines, the ith line( i starts from 1) contains a integer indicating the cost to make a mooncake during the ith hour . The cost is no more than 10000. Jan 1st 2000 0 o'clock belongs to the 1st hour, Jan 1st 2000 1 o'clock belongs to the 2nd hour, …… and so on.

(0<N <= 2500; 0 < M,T <=100000; 0<=S <= 200; R<=10000 ; 0<=H<24)

The input ends with N = 0 and M = 0.

分析:

        大致思想就是读入时间,然后换算成从0M-1之间的第x个小时,然后在【x-Tx】区间内用RMQ查找生产月饼的最小成本。然后用最小成本乘以月饼数即是该条order的成本了。

        不过这里查询最小值函数getMin返回的是最小成本的编号i,而且比较最小值的函数不是静态比较而是动态比较,并不是单纯的比较值而且要考虑S(即保存成本)和两者之间的时间差。

        例如在第3小时生成的成本是4,在第5小时生产的成本是6,但是保存月饼每小时开销是2.那么3小时和5小时比较的情况是(假设生成1块月饼):3小时生成了一块月饼花费了4,但是需要保存到5小时又花费了4的保存成本,所以一共花费了8的成本。但是5小时可以直接生成月饼花费6不用保存,所以最小值时5小时。

AC代码:140ms

<span style="font-size:18px;"><span style="font-size:18px;">#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int getmonth(char s[])
{
    if(strcmp(s,"Jan")==0)return 1;
    else if(strcmp(s,"Feb")==0)return 2;
    else if(strcmp(s,"Mar")==0)return 3;
    else if(strcmp(s,"Apr")==0)return 4;
    else if(strcmp(s,"May")==0)return 5;
    else if(strcmp(s,"Jun")==0)return 6;
    else if(strcmp(s,"Jul")==0)return 7;
    else if(strcmp(s,"Aug")==0)return 8;
    else if(strcmp(s,"Sep")==0)return 9;
    else if(strcmp(s,"Oct")==0)return 10;
    else if(strcmp(s,"Nov")==0)return 11;
    else if(strcmp(s,"Dec")==0)return 12;
}
int days[]={0,31,28,31,30,31,30,31,31,30,31,30,31};//普通年的每月天数
bool isleap(int y)
{
    if(y%400==0 || (y%100!=0 && y%4==0))return true;
    return false;
}
struct node
{
    char mon[10];
    int y,m,d,h;
    int R;
    int index;//表示读入的时间是从2000年1月1日0时算起的第几个小时,从1开始计数
    void input()
    {
        scanf("%s%d%d%d%d",mon,&d,&y,&h,&R);
        if(y<2000)//非法
        {
            index = -1;
            return ;
        }
        int m = getmonth(mon);
        index=0;
        for(int i=2000;i<y;i++)//整年之差
        {
            if(isleap(i))index += 366*24;
            else index +=365*24;
        }
        for(int i=1;i<m;i++)//整月之差
        {
            index += days[i]*24;
        }
        if(isleap(y) && m>2)index +=24;//最后一年也是闰年且超过了2月
        index += (d-1)*24;//整日之差
        index +=h+1;//小时之差,不过index从1开始计数,所以是h+1
    }
}nodes[3000];
const int MAXN=100000+1000;
int a[MAXN];//a[i]表示第i小时做月饼的初始成本
int dmin[MAXN][20];
int n,m,T,S;
int minv(int i,int j)
{
    if(i==j)return i;
    else if(i<j)
    {
        return a[i]+(j-i)*S<=a[j]?i:j;
    }
    else
    {
        return a[j]+(i-j)*S<=a[i]?j:i;
    }
}
void initMin(int n)
{
    for(int i=1;i<=n;i++)dmin[i][0]=i;
    for(int j=1;(1<<j)<=n;j++)
        for(int i=1;i+(1<<j)-1<=n;i++)
        {
            dmin[i][j] = minv(dmin[i][j-1] , dmin[i+(1<<(j-1))][j-1]);
        }

}
int getMin(int L,int R)
{
    int k=0;
    while((1<<(k+1))<=R-L+1)k++;
    return minv(dmin[L][k] , dmin[R-(1<<k)+1][k]);
}
int main()
{
    while(scanf("%d%d",&n,&m)==2&&n&&m)
    {
        for(int i=1;i<=n;i++)
            nodes[i].input();
        scanf("%d%d",&T,&S);
        for(int i=1;i<=m;i++)
            scanf("%d",&a[i]);
        initMin(m);
        long long ans=0;
        for(int i=1;i<=n;i++)
        {
            int index = nodes[i].index;
            if(index<0||index>m)continue;
            int min_i = getMin(max(1,index-T),index);
            ans += (a[min_i]+(index-min_i)*S)*nodes[i].R;
        }
        printf("%I64d\n",ans);
    }
    return 0;
}
</span></span>


你可能感兴趣的:(ACM)