1836: 【USACO】Buying Feed(购买饲料)

该博客讨论了一个关于农民约翰购买和运输饲料的问题。给定饲料需求、行驶成本和不同商店的位置及价格,需要找到最低成本的购买和运输策略。博客通过一个实例解释了如何计算最小费用,并提供了一个解决方案,即动态规划算法来求解这个问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1836: 【USACO】Buying Feed(购买饲料)

时间限制: 2.000 Sec  内存限制: 64 MB
提交: 109  解决: 34
[命题人:][下载数据: 80]

提交状态报告

题目描述

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.
/* FJ需要去镇上购买K(1<=K<=10,000)磅饲料.当带着K磅重的饲料时,每走1英里就会花约翰K*K的钱;显然,走D英里的话就要花D*K*K的钱. FJ可以从标号为1到N的N(1 <= N <= 500)个商店中购买饲料.这些商店都坐落在一个长度为E(1<=E<=500)的X坐标轴上.商店i位于数轴上X_i(0 < X_i < E)这个位置,可以以单价为C_i(1 <= C_i <= 10,000,000)的价格卖给约翰F_i(1 <= F_i <= 10,000)磅的饲料.特别的,在X轴上的一个位置可能有多个商店. FJ一开始在数轴的0位置上,只可以向着正方向开,最后带着K磅的饲料到达E位置.他可以随意停车购买随意多的饲料,只要在商店的能力范围之内. 那么,FJ最小需要花多少钱用在购买K磅饲料和带着它们去E处呢.FJ知道他总可以买到足够的饲料. 考虑一下这个例子,在长度为5的X轴的1,3,4位置有三个商店,就像这样:

      0   1   2   3   4   5  X轴
      +---|---+---|---|---+
            1           1    1      可以卖出饲料的数量
            1           2    2      单价

FJ需要两磅的饲料,最经济的做法是在第二个商店和第三个商店中各购买一个单位的饲料.这样的话,花在饲料上的钱时1*2+1*2=4,从0到3不需要行走的花费,因为没有饲料,而从3到4需要花费1*1*1=1的路费,而从4到5需要花费1*2*2=4的路费,这样一共是4+1+4=9的花费,这是最小的了. */

输入

* 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
/* 第1行:三个整数K,E,N
第2..N+1行:第i+1行的三个整数代表,X_i,F_i,C_i. */

输出

* Line 1: A single integer that is the minimum cost for FJ to buy and transport the feed
/* 第一行:一个整数,代表最小花费 */

样例

输入  复制

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

输出  复制

9

来源/分类

USACO 2010 November Gold 

AC

#include<bits/stdc++.h>
using namespace std;
const long long  maxn=505;
int K,E,n;
struct node
{
    long long  x,f,c;
}a[maxn];
bool cmp(node a,node b)
{
    return a.x<b.x;
}
long long  f[maxn][maxn*20];
long long  dis[maxn];
int main()
{
    scanf("%lld%lld%lld",&K,&E,&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld%lld%lld",&a[i].x,&a[i].f,&a[i].c);
    }
    a[++n]=(node){E,0,0};
    sort(a+1,a+n+1,cmp);
    memset(f,0x3f,sizeof(f));
    /*for(long long  i=1;i<=k;i++)
    {
        f[1][i]=a[1]*k;
    }*/
    f[0][0]=0;
    for(int i=1;i<=n;i++)
    {
        deque < long long > q;
        for(int j=0;j<=K;j++)
        {
            while(!q.empty() && j-q.front()>a[i-1].f)
            q.pop_front();
            if(f[i-1][j]!=0x3f3f3f3f)
            {
                while(!q.empty()&&f[i-1][q.back()]-a[i-1].c*q.back()>=f[i-1][j]-a[i-1].c*j)
                q.pop_back();
                q.push_back(j);
            }
            long long  k=q.front();
            if(!q.empty())
            f[i][j]=f[i-1][k]-a[i-1].c*k+(a[i].x-a[i-1].x)*j*j+a[i-1].c*j;
        }
    }
    printf("%lld",f[n][K]);
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值