当前位置: 首页 > 工具软件 > Yogurt > 使用案例 >

NOI 2393:Yogurt factory【2019北大推免E】

晏卓君
2023-12-01

NOI 2393:Yogurt factory【2019北大推免E】

  • 查看

  • 提交

  • 统计

  • 提示

  • 提问

  • 总时间限制:

    1000ms

  • 内存限制:

    65536kB

  • 描述

    The cows have purchased a yogurt factory that makes world-famous Yucky Yogurt. Over the next N (1 <= N <= 10,000) weeks, the price of milk and labor will fluctuate weekly such that it will cost the company C_i (1 <= C_i <= 5,000) cents to produce one unit of yogurt in week i. Yucky’s factory, being well-designed, can produce arbitrarily many units of yogurt each week. Yucky Yogurt owns a warehouse that can store unused yogurt at a constant fee of S (1 <= S <= 100) cents per unit of yogurt per week. Fortuitously, yogurt does not spoil. Yucky Yogurt’s warehouse is enormous, so it can hold arbitrarily many units of yogurt. Yucky wants to find a way to make weekly deliveries of Y_i (0 <= Y_i <= 10,000) units of yogurt to its clientele (Y_i is the delivery quantity in week i). Help Yucky minimize its costs over the entire N-week period. Yogurt produced in week i, as well as any yogurt already in storage, can be used to meet Yucky’s demand for that week.

  • 输入

    • Line 1: Two space-separated integers, N and S. * Lines 2…N+1: Line i+1 contains two space-separated integers: C_i and Y_i.
  • 输出

    • Line 1: Line 1 contains a single integer: the minimum total cost to satisfy the yogurt schedule. Note that the total might be too large for a 32-bit integer.
  • 样例输入

    4 5
    88 200
    89 400
    97 300
    91 500
    
  • 样例输出

    126900
    
  • 提示

    OUTPUT DETAILS: In week 1, produce 200 units of yogurt and deliver all of it. In week 2, produce 700 units: deliver 400 units while storing 300 units. In week 3, deliver the 300 units that were stored. In week 4, produce and deliver 500 units.

题解

  • 子问题:dp[i]:完成week[:i]的所有demand需要的最少cost

    • 证明最优子结构(假设问题的最优解不蕴含子问题的最优解,即子问题存在更优的解):dp[i]是完成week[:i]的所有demand需要的最少cost,其中完成week[:i-1]的所有demand需要的cost部分,假设不是最优(即不满足最优子结构性质),即存在更低的完成week[:i-1]的所有demand需要的cost,则这个更优解和dp[i]中完成week[i]的demand部分可以组合成问题dp[i]的最优解,与最优性矛盾

  • 更新:dp[i]=dp[i-1]+选择week[:i]中在week[i]时单价最低的week生产本周的所有demand

    • week[j]在week[i]时单价:cost[j]+S*(i-j) (初始生产的单价,加上每周存储的单价)
    • note:
      • dp[i]对于dp[:i-1]只需要知道dp[i-1],因此可以省略数组使用变量dp
      • 更新对于当前week week[i],week[:i]的单价:(考虑从week[i-1]来的关系)
        • cost[j]+S*(i-j) = cost[j]+S*(i-1-j) +S
          • 进一步发现,所有之前已经有单价的单价都是同步+S,因此进入新的一周,最低price一定是min((原先的最低price+S), 新周的price)
          • 进一步的,这样的话cost也不用数组存了
        • 看到可以用在week[i-1]的单价来获取week[i]的单价,避免乘法
  • 初始:dp[0]:前面没有周,必须本周完成demand,因此dp[0]=c[0]*d

  • 时间复杂度:对于week[i]常数操作,因此复杂度是O(n),N<=104<1-9是可以的

  • 数据范围:

    • 全周代价C*Y*N=5000*104*104 = 5*1011>2*109用int不行要用long long
    • 单价:1 <= C_i <= 5,000,1 <= S <= 100,1 <= N <= 10,000,则最大单价5000+100*10000<10^9,可以用int,不过和demand乘法时需要是long long乘法,所以建议用long long
#define MAXN 10005
int main()
{
    int N,S;
    cin>>N>>S;
    long long d,c;//demand, cost
    cin>>c>>d;//N>=1, this must be safe
    long long dp=c*d;
    long long min_price=c;
    for(int i=1; i<N; ++i){
        cin>>c>>d;
        //update min_price
        min_price=min(c,min_price+S);
        //update dp
        dp += min_price*d;
    }
    cout<<dp<<endl;
    return 0;
}
 类似资料: