• 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;
    }
    
    
  • 相关阅读:
    linux常用命令
    mysql 开发基础系列20 事务控制和锁定语句(上)
    sql server 性能调优之 资源等待 CXPACKET
    mysql 开发基础系列19 触发器
    mysql 开发基础系列18 存储过程和函数(下)
    mysql 开发基础系列17 存储过程和函数(上)
    sql server 性能调优之 资源等待PAGEIOLATCH
    mysql 开发基础系列16 视图
    mysql 开发基础系列15 索引的设计和使用
    sql server 性能调优之 当前用户请求分析 (1)
  • 原文地址:https://www.cnblogs.com/alking1001/p/12308359.html
Copyright © 2020-2023  润新知