Inventory problem 存货问题 (DP)

Consider the following inventory problem. You are running a company that sells some large product (let’s assume you sell trucks), and predictions tell you the quantity of sales to expect over the next n months. Let di denote the number of sales you expect in month i. We’ll assume that all sales happen at the beginning of the month, and trucks that are not sold are stored until the beginning of the next month. You can store at most S trucks, and it costs C to store a single truck for a month. You receive shipments of trucks by placing orders for them, and there is a fixed ordering fee of K each time you place an order (regardless of the number of trucks you order). You start out with no trucks. The problem is to design an algorithm that decides how to place orders so that you satisfy all the demands {di}, and minimize the costs. In summary:
•There are two parts to the cost: (1) storage − it costs C for every truck on hand that is not needed that month; (2) ordering fees − it costs K for every order placed.
•In each month you need enough trucks to satisfy the demand di , but the number left over after satisfying the demand for the month should not exceed the inventory limit S.
Give an algorithm that solves this problem in time that is polynomial in n and S.

问题大意:给一家卡车公司,告诉你接下来n个月的订单需求,并且在第i个月销量为di。假设所有订货与销售均发生在月初,如果这个月没卖掉的要储存到下个月才能卖。仓库最多可以储存S量卡车,每辆卡车每个月的存储费用为C,并且每次订货无论定多少均需要花费K的订货费。如何在满足所有需求的条件下最小化支出。(算法的时间复杂度需要是n与S的一个多项式。)

基本思路:
使用动态规划算法,
先考虑有递归式的数组是几维的,
考虑到我们每考虑一个新的月份时,均需要考虑该月的前一月的剩余卡车量和本月的di,若前一个月的卡车剩余量能够满足本月的销量,则不需要再定货,反之需要再定。

考虑其子问题,假设月份比原来少,使用数组T[i,s]表示从第i个月到第n个月的最优解,表示从i~n月,起始存放数量为s时的最小开销。
有s<=S,因此整个表格为[n,S]故总时间为O(nS)//也可以根据题目的这个要求倒推

下一步写出递推公式
知道了第第i+1个月的数组值后求第i个月的
分为两种情况
//T[i+1,s’]s’在0~S间全为已知
1.在i月开始时已有库存s比第i个月销量的多,这个月不用买了,剩下的库存都放到第i+1月去,由于算到这步时默认T[i+1,s-di]已知,直接加上即可。
T[i,s]=C*(s-di)+T[i+1,s-di];
2.前一个月剩的比第i个月销量少,这个月还要买
但由于此时购买数量的多少无法确定,并且数量的多少会影响最小费用,故需要枚举计算。
min(s’=0~S){s’*C+T[i+1,s’]}//s’表示这个月买完后剩下的,除了存储费以外还要加上固定购买费k
T[i,s]=k+min(s’=0~S){s’*C+T[i+1,s’]}
//s’表示这个月满足了订单后的剩余量,我们只关注下个月开始有多少,那么这个月定了多少和上个月剩下来的量的分配是如何其实不需要考虑

由上式可以得出从第i个月开始在月初库存为s时,到第n个月的最小总费用。是最小的原因:如果情况1显然可见是最优策略,如果情况2,由于遍历获得了这个月如何购买是最优情况因此也能得到是最优解。

//以这种思路做Bottom up的计算
define maxInt=1000011int T[n,S]={0};
for(int s=0;s<=S;s++)
{
  //单独设置最底下一层的值,即第n个月时不同的s对应的T[n];
  /*由于第n月是最后一个月份,我们需要使得订货量正好满足而不应该有剩下的
  如果剩下的就是浪费,因此不应该让s>di,如果大于了,我们应该
  让前面第n-1月份选择最优解时不选择剩下大于di的量,可以通过
  设置T[n,s1](s1>d[n])=+∞来避免
  */
  if(s<d[n])
  {
  //第n个月需要进货
  T[n,s]=k;
  }
  else if(s==d[n])
  {
  //恰好不需要进货
  T[n,s]=0;
  }
  else
  {
  //数量超过不应该选择
  T[n,s]=maxInt;
  } 
}
for(int i=n-1;i>=1;i--)
{
  for(int s=0;s<=S;s++)
  {
    if(s<=d[i])
    {
    //数量不够,需要进货
      for(int s'=0;s'<=S;s'++)
      {
      //s'为该月满足需求后的剩余量
        T[i,s]=k+min(s'*C+T[i+1,s']);
      }
    }
    else
    {
    //库存够
      sleft=s-d[i];
      T[i,s]=C*sleft+T[i+1,sleft];
   }

}

T[1,0]即为所求

DP问题的关键点是找到子问题以及递推公式,这种较为简单的DP问题的子问题的变量数一般为1/2,依据具体题目而定,子问题一般为从前往后取i个或从后往前i个。

与这道题目类似的还有poj 2393: Yogurt factory
使用贪心问题求解。
poj 2393: Yogurt factory

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值