zoukankan      html  css  js  c++  java
  • BZOJ_1229_[USACO2008 Nov]toy 玩具_三分+贪心

    BZOJ_1229_[USACO2008 Nov]toy 玩具_三分+贪心

    Description

    玩具 [Chen Hu, 2006] Bessie的生日快到了, 她希望用D (1 <= D <= 100,000; 70%的测试数据都满足 1 <= D <= 500)天来庆祝. 奶牛们的注意力不会太集中, 因此Bessie想通过提供玩具的方式来使它们高兴. 她已经计算出了第i天需要的玩具数T_i (1 <= T_i <= 50). Bessie的幼儿园提供了许多服务给它们的奶牛程序员们, 包括一个每天以Tc (1 <= Tc <= 60)美元卖出商品的玩具店. Bessie想尽可能的节省钱, 但是Farmer John担心没有经过消毒的玩具会带来传染病(玩具店卖出的玩具是经过消毒的). 有两种消毒的方式. 第1种方式需要收费C1美元, 需要N1个晚上的时间; 第2种方式需要收费 C2美元, 需要N2个晚上的时间(1 <= N1 <= D; 1 <= N2 <= D; 1 <= C1 <= 60; 1 <= C2 <= 60). Bessie在party结束之后把她的玩具带去消毒. 如果消毒只需要一天, 那么第二天就可以拿到; 如果还需要一天, 那么第三天才可以拿到. 作为一个受过教育的奶牛, Bessie已经了解到节约的意义. 帮助她找到提供玩具的最便宜的方法.

    Input

    * 第 1 行: 六个用空格隔开的整数 D, N1, N2, C1, C2, Tc

    * 第 2..D+1 行: 第 i+1 行包含一个整数: T_i

    Output

    第 1 行: 提供玩具所需要的最小费用.

    Sample Input

    4 1 2 2 1 3
    8
    2
    1
    6

    Sample Output

    35


    三分到底买多少玩具。

    打个表发现确实是单峰函数。。证明的话不会。

    可能是因为跑费用流时单位费用和最短路单调吧。

    贪心还是比较简单的。

    优先用已经买好的,因为这个费用是0。

    否则用慢洗的,这个可以维护一个指针。

    如果慢洗洗不过来就用快洗,快洗要尽可能用最近剩下的,因为要给慢洗留出时间,用一个栈来维护。

    注意这里的慢洗,快洗是根据数据的,费用少的那个作为慢洗(不管时间)

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 100050
    int c1,c2,n1,n2,n,t[N],tc,b[N],S[N],top;
    int check(int x) {
        int re=x*tc,i,l=1; top=0;
        for(i=1;i<=n;i++) b[i]=t[i];
        for(i=1;i<=n;i++) {
            int lft=t[i];
            if(x>=lft) x-=lft,lft=0;
            else lft-=x,x=0;
            while(l<=i-n1&&lft) {
                if(lft<=b[l]) re+=c1*lft,b[l]-=lft,lft=0;
                else re+=c1*b[l],lft-=b[l],b[l]=0,l++;
            }
            while(top&&lft) {
                int u=S[top-1];
                if(lft<=b[u]) re+=c2*lft,b[u]-=lft,lft=0;
                else re+=c2*b[u],lft-=b[u],b[u]=0,top--;
            }
            if(i-n2+1>=1) S[top++]=i-n2+1;
            if(lft) return 1<<30;
        }
        return re;
    }
    int main() {
        scanf("%d%d%d%d%d%d",&n,&n1,&n2,&c1,&c2,&tc);
        if(c1>c2) swap(c1,c2),swap(n1,n2);
        int i,sum=0;
        for(i=1;i<=n;i++) scanf("%d",&t[i]),sum+=t[i];
        int l=t[1],r=sum;
        while(r-l>6) {
            int m1=(l+l+r)/3,m2=(l+r+r)/3;
            if(check(m1)<check(m2)) r=m2;
            else l=m1;
        }
        int ans=1<<30;
        for(i=l;i<=r;i++) ans=min(ans,check(i));
        printf("%d
    ",ans);
    }
    
  • 相关阅读:
    solr的学习
    springMvc学习地址新
    mybatis教程
    spring学习地址
    spring思想分析
    java中反射讲解及实例
    学习地址
    linux常用命令
    XML Data Type Methods(一)
    Ruby中 使用Builder Xml Markup 操作XML
  • 原文地址:https://www.cnblogs.com/suika/p/9126852.html
Copyright © 2011-2022 走看看