zoukankan      html  css  js  c++  java
  • HDU 4122 单调队列

    HDU 4122 单调队列

    题意

    给定n个订单,在相应时刻都要生产num[i]个月饼,给出m个可以生产的时刻和这个时刻生产单个产品的费用cost[i],每个月饼可以存储T个小时的保质期,但是存储月饼也是要花钱的,每小时存储需要花费S,求出最小花费。

    解题思路

    一定要读清楚题意。

    其实对于每个订单都有一个确定的生产时刻(最优的情况下),并且只有一个,我们可以使用单调队列来求出这个最优时刻。这个进队列的判断还是有点特殊的,如果当前进队列的单价花费cost[i] <= cost[que[tail-1]]+S*(i-que[tail-1]),(这里的que[]数组是用来模拟队列的,que中存储的是cost[]的下标。)就需要队尾出元素,因为队尾的元素不如当前时刻的花费更优。单调队列中还有一个要点是区间长度,这里就是用T来担当了,虽然队首的元素时刻的花费(相对当前时刻来说)最优,但是过了保质期也不行啊。这样我们就可以开做了。

    代码实现

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<string>
    #include<stack>
    #include<queue>
    #include<map>
    typedef long long ll;
    using namespace std;
    const double esp=1e-6;
    const int inf=0x3f3f3f3f;
    const int MAXN=1E5+50;
    int n, m, time[2507], T, S, cost[MAXN], q[MAXN];
    ll num[2507];
    int getmonth(char* s)
    {
    	if(strcmp(s, "Jan") == 0) return 1;
    	if(strcmp(s, "Feb") == 0) return 2;
    	if(strcmp(s, "Mar") == 0) return 3;
    	if(strcmp(s, "Apr") == 0) return 4;
    	if(strcmp(s, "May") == 0) return 5;
    	if(strcmp(s, "Jun") == 0) return 6;
    	if(strcmp(s, "Jul") == 0) return 7;
    	if(strcmp(s, "Aug") == 0) return 8;
    	if(strcmp(s, "Sep") == 0) return 9;
    	if(strcmp(s, "Oct") == 0) return 10;
    	if(strcmp(s, "Nov") == 0) return 11;
    	if(strcmp(s, "Dec") == 0) return 12;
    } 
    int days[15] = {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;
    	else return false; 
    }
    
    int get_hours(int y, int m, int d, int h)
    {
    	int ans=0;
    	for(int i=2000; i < y; i++)
    	{
    		if(isleap(i))  
    			ans+=366*24;
    		else ans+=365*24;
    	}	
    	for(int i=1; i<m; i++)
    		ans += days[i]*24;
    	if(isleap(y) && m > 2)
    		ans += 24;
    	ans+=(d-1)*24;
    	ans+=h;
    	return ans;
    }
    int main()
    {
    	while(scanf("%d%d", &n, &m)!=EOF)
    	{
    		memset(time, 0, sizeof(time));
    		if(n==0 && m==0) break;
    		for(int i=0; i<n; i++)
    		{
    			char mon[10];
    			int d, y, h;
    			scanf("%s%d%d%d%lld", mon, &d, &y, &h, &num[i]);
    			time[i]=get_hours(y, getmonth(mon), d, h);
    		}
    		scanf("%d%d",&T,&S);
            int tail=0,head=0,k=0;
            ll sum=0;
            for(int i=0; i<m; i++)
            {
                scanf("%d",&cost[i]);
                while(head<tail && cost[q[tail-1]]+S*(i-q[tail-1]) >= cost[i])
    				tail--;
                q[tail++] = i;
                while(q[head] < i - T)
    				head++;
                while(i == time[k])//可能同一个时刻有多个订单,题目说了,订单时间是有序的。
                {
                    sum += num[k] * (cost[q[head]] + S*(i-q[head]));
                    k++;
                }
            }
            printf("%lld
    ", sum);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    python实现从生成器中取固定角标的元素
    python-高阶函数
    git学习手册
    python批量进行文件修改操作
    python第一站
    LoadRunner,一个简单的例子
    python3中urllib2的问题
    gitlab 随笔
    sed 删除文本
    sed 修改文本
  • 原文地址:https://www.cnblogs.com/alking1001/p/12308359.html
Copyright © 2011-2022 走看看