zoukankan      html  css  js  c++  java
  • Alice's mooncake shop

    题目大意:

    一个月饼店开m个小时(24小时营业),只在整点做月饼,做月饼的能力非常强。现在只需要考虑成本的问题。给m个cost值,cost[i]表示第i个小时做1个月饼的代价。

    再给n个时间,从2000年1月1日0时开始计算。表示订单的截止时间。当然为了节约成本,可以提前趁成本不高的时候做月饼。但是月饼有保质期,t天,月饼放冰箱保存也需要代价,一天花费s。

    现在求完成n个订单最小代价。

    分析:

    对于第i个订单,首先计算出是第ti个营业时间。这里考虑每个月饼的单价。所以第i个订单的月饼只能在[ti - t,ti]做。考虑时间j有个订单,假设时间i完成代价是最小的。那么第j个订单的代价就是cost[i] + (j - i) * s。我们用单调队列去维护下这个区间就可以了

    #include <algorithm>
    #include <string>
    #include <string.h>
    #include <vector>
    #include <map>
    #include <stack>
    #include <set>
    #include <queue>
    #include <math.h>
    #include <cstdio>
    #include <iomanip>
    #include <time.h>
    #include <bitset>
    #include <cmath>
    #include <sstream>
    #include <iostream>
    
    #define LL long long
    #define INF 0x3f3f3f3f
    #define ls nod<<1
    #define rs (nod<<1)+1
    
    const double eps = 1e-10;
    const int maxn = 1e5 + 10;;
    const LL mod = 1e9 + 7;
    
    int sgn(double a){return a < -eps ? -1 : a < eps ? 0 : 1;}
    using namespace std;
    
    struct node {
        LL val,idx;
    };
    
    LL cost[maxn],ti[maxn];
    LL m,n,h,r,s,t;
    int days[2][13] = {{0,31,28,31,30,31,30,31,31,30,31,30,31},
                       {0,31,29,31,30,31,30,31,31,30,31,30,31}
    };
    
    int getmon(char ss[])
    {
        if(strcmp(ss,"Jan") == 0)
            return 1;
        else if(strcmp(ss,"Feb") == 0)
            return 2;
        else if(strcmp(ss,"Mar") == 0)
            return 3;
        else if(strcmp(ss,"Apr") == 0)
            return 4;
        else if(strcmp(ss,"May") == 0)
            return 5;
        else if(strcmp(ss,"Jun") == 0)
            return 6;
        else if(strcmp(ss,"Jul") == 0)
            return 7;
        else if(strcmp(ss,"Aug") == 0)
            return 8;
        else if(strcmp(ss,"Sep") == 0)
            return 9;
        else if(strcmp(ss,"Oct") == 0)
            return 10;
        else if(strcmp(ss,"Nov") == 0)
            return 11;
        else if(strcmp(ss,"Dec") == 0)
            return 12;
        else return -1;
    }
    LL getid(int y,int m,int d,int h)
    {
        int loop = (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
        LL ret = d - 1;
        for(int i = 1;i < m;i ++)
            ret += days[loop][i];
        for(int i = 2000;i < y;i ++)
        {
            if((i % 4 == 0 && i % 100 != 0) || i % 400 == 0)
                ret += 366;
            else
                ret += 365;
        }
        ret *= 24;
        ret += h;
        return ret + 1;
    }
    char mo[34];
    int da,ye;
    LL rr[maxn];
    
    int main() {
        while (~scanf("%lld%lld",&n,&m)) {
            if (n == 0 && m == 0)
                break;
            for(int i = 1;i <= n;i ++) {
                scanf("%s",mo);
                scanf("%d%d%lld%lld",&da,&ye,&h,&r);
                ti[i] = getid(ye,getmon(mo),da,h);
                rr[i] = r;
            }
            scanf("%lld%lld",&t,&s);
            for (int i = 1;i <= m;i++) {
                scanf("%lld",&cost[i]);
            }
            LL ans = 0;
            deque<node> q;
            for (int i = 1,j = 1;i <= m && j <= n;i++) {
                while (!q.empty() && q.back().val+(i-q.back().idx)*s >= cost[i])
                    q.pop_back();
                node nd;
                nd.val = cost[i],nd.idx = i;
                q.push_back(nd);
                while (!q.empty() && q.front().idx < i-t)
                    q.pop_front();
                while (ti[j] == i) {
                    ans += rr[j]*(q.front().val + (i-q.front().idx)*s);
                    j++;
                }
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    Fiddler的使用
    vue后台管理系统搭建
    有效的山脉数组
    从中序与后序遍历序列构造二叉树
    从前序与中序遍历序列构造二叉树
    最大二叉树
    填充每个节点的下一个右侧节点指针
    二叉树展开为链表
    翻转二叉树
    Java判断字符串是否为数字
  • 原文地址:https://www.cnblogs.com/-Ackerman/p/12403700.html
Copyright © 2011-2022 走看看