zoukankan      html  css  js  c++  java
  • BZOJ 2059 [Usaco2010 Nov]Feed 购买饲料

    BZOJ_2059

        本来打算想想费用流的,但是既然给的是直线,八成就是让dp了,否则完全可以给成图的。

        不妨用f[i][j]表示递推到第i个商店时,在前i-1个商店一共买了j的饲料,这样就有状态转移方程f[i][j]=min{f[i-1][k]+(j-k)*C[i-1]}+j*j,其中0<=j-k<=F[i-1]。这样裸着做的话,复杂度是没法承受的,但如果把min{}里的j拿出来的话就会得到f[i][j]=min{f[i-1][k]-k*C[i-1]}+j*C[i-1]+j*j,这样min里面的只和k有关,而且k是要满足一定范围的,这时我们可以用单调队列来维护f[i-1][k]-k*C[i-1]的最小值,这样每次决策就是O(1)了。

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define MAXN 510
    #define MAXK 10010
    #define INF 0x3f3f3f3f3f3f3f3fll
    typedef long long LL;
    struct Shop
    {
        int x, c, f;
        bool operator < (const Shop &t) const
        {
            return x < t.x;
        }
    }shop[MAXN];
    int N, E, K, q[MAXN];
    LL f[MAXN][MAXK];
    void init()
    {
        for(int i = 0; i < N; i ++)
            scanf("%d%d%d", &shop[i].x, &shop[i].f, &shop[i].c);
        std::sort(shop, shop + N);
    }
    void solve()
    {
        for(int i = 0; i <= N; i ++)
            for(int j = 0; j <= K; j ++) f[i][j] = INF;
        f[0][0] = 0;
        shop[N].x = E;
        for(int i = 1; i <= N; i ++)
        {
            int front = 0, rear = 0;
            for(int j = 0; j <= K; j ++)
            {
                while(front < rear && j - q[front] > shop[i - 1].f) ++ front;
                if(f[i - 1][j] != INF)
                {
                    while(front < rear)
                    {
                        int k = q[rear - 1];
                        if(f[i - 1][k] - (LL)k * shop[i - 1].c < f[i - 1][j] - (LL)j * shop[i - 1].c) break;
                        -- rear;
                    }
                    q[rear ++] = j;
                }
                if(front < rear)
                {
                    int k = q[front];
                    f[i][j] = f[i - 1][k] + (LL)(j - k) * shop[i - 1].c + (LL)j * j * (shop[i].x - shop[i - 1].x);
                }
            }
        }
        printf("%lld\n", f[N][K]);
    }
    int main()
    {
        while(scanf("%d%d%d", &K, &E, &N) == 3)
        {
            init();
            solve();
        }
        return 0;
    }
  • 相关阅读:
    DigitalOcean上使用Tornado+MongoDB+Nginx+Supervisor+DnsPod快速搭建个人博客
    创业三年来的一些感想
    创业三年来的一些感想
    ViEmuVS2013-3.2.1 破解
    瘋子C语言笔记(指针篇)
    瘋子C语言笔记(结构体/共用体/枚举篇)
    瘋子C++笔记
    petalinux add pre-build application to rootfs compile faliure solution
    QA Issue: No GNU_HASH in the elf binary
    视觉SLAM——特征点法与直接法对比以及主流开源方案对比 ORB LSD SVO DSO
  • 原文地址:https://www.cnblogs.com/staginner/p/2719681.html
Copyright © 2011-2022 走看看