zoukankan      html  css  js  c++  java
  • EOJ440 Buying Feed

    EOJ440 Buying Feed

    Time Limit: 2000MS   Memory Limit: 65536K
    Total Submits: 135   Accepted: 16
     

    Description

    Farmer John needs to travel to town to pick up K (1 <= K <= 10,000) pounds of feed. Driving a mile with K pounds of feed costs FJ K*K cents; driving D miles with K pounds of feed in his truck costs FJ D*K*K cents. 

    FJ can purchase feed from any of N (1 <= N <= 500) stores (conveniently numbered 1..N) that sell feed. Each store is located on a segment of the X axis whose length is E (1 <= E <= 500) miles. Store i is at location X_i (0 < X_i < E) on the number line and can sell FJ as much as F_i (1 <= F_i <= 10,000) pounds of feed at a cost of C_i (1 <= C_i <= 10,000,000) cents per pound. Surprisingly, a given point on the X axis might have more than one store. 

    FJ starts driving at location 0 on this number line and can drive only in the positive direction, ultimately arriving at location E with at least K pounds of feed. He can stop at any of the feed stores along the way and buy any amount of feed up to the the store's limit. 

    What is the minimum amount FJ must pay to buy and transport the K pounds of feed? FJ knows he can purchase enough feed. 

    Consider this example where FJ needs two pounds of feed which he must purchase from some of the three stores at locations 1, 3, and 4 on a number line whose range is 0..5: 
          0   1   2   3   4   5  X
    +---|---+---|---|---+
    1 1 1 Available pounds of feed
    1 2 2 Cents per pound

    It is most economical for FJ to buy one pound of feed from both the second and third stores. He must pay two cents to buy each pound of feed for a total cost of 4. FJ's driving from location 0 to location 3 costs nothing, since he is carrying no feed. When FJ travels from 3 to 4 he moves 1 mile with 1 pound of feed, so he must pay 1*1*1 = 1 cents. 

    When FJ travels from 4 to 5 he moves one mile with 2 pounds of feed, so he must pay 1*2*2 = 4 cents. 

    His feed cost is 2 + 2 cents; his travel cost is 1 + 4 cents. The total cost is 2 + 2 + 1 + 4 = 9 cents. 

    Input

    * Line 1: Three space-separated integers: K, E, and N 

    * Lines 2..N+1: Line i+1 contains three space-separated integers: X_i, F_i, and C_i 

    Output

    * Line 1: A single integer that is the minimum cost for FJ to buy and transport the feed

    Sample Input

    2 5 3 
    3 1 2 
    4 1 2 
    1 1 1 

    Sample Output

    9
    ********************************************************
    题目大意:一条直线上坐落着n个商店,一个人从0出发到e点,他到e点时必须买齐k件物品。他的花费有两个方面:1、在商店买物品,每个商店物品的单价不尽相同,每个商店提供的物品数量有上限;2、他背着i件物品走过L米要交路费L*i*i的数量。问最后的时候,求他的花费最小。
    解题思路:dp+单调队列优化。
    话说单调队列优化的dp写过,但没这么正规地写过。
    状态转移方程:dp[h][j]表示到达h这个商品,身上有了j件物品所需的最小花费;
    dp[h][j]=min{dp[h-1][i]+L*i*i+C*(j-i)},1<=i<j
    淳朴地状态转移需要n^2的复杂度。借助单调队列优化:
    令S[k]表示当i取成k时候的值:
    取k1<k2,
    S[k1]-S[k2]=dp[h-1][k1]-dp[h-1][k2]+L*(k1*k1-k2*k2)-C*(k1-k2)
    令S[k1]-S[k2]<0
    dp[h-1][k1]-dp[h-1][k2]+L*(k1*k1-k2*k2)-C*(k1-k2)<0;
    因为实际的时候,k2=k1+1
    所以,当dp[h-1][k]-dp[h-1][k+1]-L*(2*k1+1)+C<0的时候有最优解。
    于是可以用单调队列优化。
    下面引用论文原文:

    单调队列的优化的主要思路:能优化的就是状态转移的j,(动态规划主要的优化思路)那么对于j来说,我们必须要构造一个 j1与j2之间的关系,这个关系必须保证 j1<j2,也就是j在单调递增时,那个关系也必须单调(像本题中的g的关系),并且j与当前的状态i没有直接的关系。

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #define N 10005
    #define M 505
    using namespace std;
    
    struct Node
    {
        long long x,f,c,tx;
        bool operator<(const Node & a)const
        {
            return x<a.x;
        }
    }node[M];
    long long k,e,n;
    long long dp[M][N];
    
    void re(void)
    {
        scanf("%I64d%I64d%I64d",&k,&e,&n);
        for(int i=1;i<=n;i++)
            scanf("%I64d%I64d%I64d",&node[i].x,&node[i].f,&node[i].c);
    }
    
    void run(void)
    {
        sort(node+1,node+1+n);
        memset(dp,-1,sizeof(dp));
        for(int i=2;i<=n;i++)
            node[i].tx=node[i].x-node[i-1].x;
        for(int i=0;i<=k&&i<=node[1].f;i++)
            dp[1][i]=node[1].c*i;
        for(int i=2;i<=n;i++)
        {
            dp[i][0]=0;
            int top=0,ed=0;
            for(int j=1;j<=k;j++)
            {
                ed++;
                for(;top<=ed-1;top++)
                {
                    if(dp[i-1][top+1]==-1)break;
                    if(j-top>node[i].f)continue;
                    int a=dp[i-1][top+1]-dp[i-1][top]+node[i].tx*(2*top+1)-node[i].c;
                    if(a>0)break;
                }
                if(j-top>node[i].f)break;
                dp[i][j]=dp[i-1][top]+node[i].tx*top*top+node[i].c*(j-top);
            }
        }
        long long ans=dp[n][k];
        ans+=k*k*(e-node[n].x);
        printf("%I64d\n",ans);
    }
    
    int main()
    {
        re();
        run();
        return 0;
    }
    

      

    也许有挫折,但这些,怎能挡住湘北前进的步伐
  • 相关阅读:
    分布式系统知识点六:分布式锁及其简单实现讲解 2 zookpeer的实现(转载)
    分布式系统知识点六:分布式锁及其简单实现讲解 1redis的实现(转载)
    分布式系统知识点五:分布式事务及其解决方案2 利用消息队列处理分布式事务(转载)
    分布式系统知识点五:分布式事务及其解决方案 1 2PC,3PC简洁(转载)
    分布式系统知识点四: 一致性hash介绍 (转载)
    分布式系统知识点三: Paxos知识2 Paxos实现简洁及MulitPaxos介绍 (转载)
    分布式系统知识点三: Paxos知识1 算法原理与推导 (转载)
    分布式系统知识点二: 分布式一致性模型分类 (转载)
    分布式系统知识点一: CAP理论 (转载)
    压缩目录下的文件
  • 原文地址:https://www.cnblogs.com/Fatedayt/p/2240227.html
Copyright © 2011-2022 走看看