苹果采购问题(DP)

Suppose you drive a pickup truck from apple market 1 to apple market n. Along the high way,
you will go through apple markets, 2, 3, …, n-1. At each market, you can buy or sell apples.
From a customer point of view, the buying price B[i] and selling price S[i] (dollar per pound)
at market i are known, 1 £ i £ n. In addition, we assume the following:
(1) You should never drive backward.
(2) Initially, the truck is empty.
(3) You should fully load the truck each time you buy apples and should sell all apples entirely
each time you sell apples.
(4) You can sell apples at most once in each market. That is, at a market, you can
(3.1) buy apples only
(3.2) sell apples only
(3.3) buy apples and then sell them at the same market
(3.4) sell apples and then buy apples at the same market
(3.5) buy apples, sell them, and buy again at the same market, but no sell the second time
(3.6) do nothing.
(5) You can sell apples a multiple number of times but at different markets.
Now, we wish to find an optimal sequence of trades in the order they are made such that
the total profit will be maximized. Here each trade is represented by a pair of (buying market,
selling market). The following figure shows an example.
If we do the following sequence of trades: (1, 1), (1, 3), (4, 5), (5, 6), then the total profit will
be (4-3)+(7-3)+(9-2)+(8-7) = 13 dollars for each pound of truck capacity.
在这里插入图片描述
(a) Please design a dynamic programming algorithm to determine an optimal trade sequence
such that the total profit is maximized. You need to define the sub-problems, find inductive
formula, and initial conditions. Pseudo code is not required.
(b) Apply your algorithm to the following example.
在这里插入图片描述

题目大意

从A到B共有n个市场,你可以在每个市场中选择购买或出售苹果,B[i]表示购入价格,S[i]表示售价,问如何选择购买出售序列使得盈利最多。
ps:
1.不能回头
2.每次购买或出售苹果必须以整卡车为单位(那我们可以假设卡车上最多放一个苹果)
3.每个市场最多买一次苹果,但可以多次出售。

设计动态规划子问题

同样对于动态规划问题,我们先考虑其子问题
我们可以知道,在这个问题中在每个市场采取何种买入策略还需知道上一次购入苹果是在哪个市场,又由于是从第一个市场往后依次经过,我们可以设置子问题为从第一个市场到第i个市场的利润为M[i](假设第i个市场已经是最后一个市场了)(若在第i个市场卖苹果则其收入也算入)

写出递推公式

(写到M[i]时是默认前面的i-1个子问题的解都已经知道了)
M[i]=max(k=1~i-1){M[k]+max{S[i]-B[k],S[i]-B[i],0}};
<解出问题:如果我在这个市场想卖,那上一个选择购入的市场是哪一个时使得我的利润最大>
(在找到了上一个可能购买点k后,在i个市场进行的操作有三种可能1.在k点购入,i点卖出 2.在i点买入,在i点卖出 3.在k~i未进行任何购买)
(又因为我们不知道到第i个点时上一个可能购买点k的位置,故用枚举法来计算出最大的)

实现细节
关于记录每一组购入市场和销售市场的问题

可以设置一个数组PAIR[i]=k表示若在市场i出售,则其购入苹果的市场为k,若未购入则令k=0;

关于初始化的问题

我们采用自底向上需要设置最底层的值
M[1]=max{S[1]-B[1],0}(要嘛在1号市场买了再卖出,要嘛就不买)
PAIR[1] = 1 if (S[1] – B[1]) > 0
PAIR[1] = 0 if (S[1] – B[1]) < 0

伪代码
MAX_Profit(B[n+1],S[n+1],PAIR[n+1],M[n+1])
{
  //先赋初值
  if(S[1]>B[1])
  {
    PAIR[1]=1;
    M[1]=S[1]-B[1];
  }
  else
  {
    PAIR[1]=0;
    M[1]=0;
  }
  for(int i=2;i<=n;i++)
  {
  //自底向上求第一个市场到每个市场的情况
     M[i]=0;//直接用这个值代表最大值可以省去中间记录最大值的中间变量
     for(int k=1;k<i;k++)
     {
       //计算M[i]
       if(M[i]<M[k]+max(S[i]-B[k],S[i]-S[i],0);
         M[i]=M[k]+max(S[i]-B[k],S[i]-S[i],0);
       //计算PAIR[i]
       if(max(S[i]-B[k],S[i]-S[i],0)==0)
         PAIR[i]=0;
       else if(max(S[i]-B[k],S[i]-S[i],0)==S[i]-B[k])
         PAIR[i]=k;
       else if(max(S[i]-B[k],S[i]-S[i],0)==S[i]-S[i])
         PAIR[i]=i;
       }  
  } 
}

可知算法的时间复杂度为O(n^2),因为其中有2个for循环

(b)对上述样例应用该算法在这里插入图片描述
可知最大收益是39,而购买顺序为
(1,2), (2, 3), (4, 4), (4,5), (6, 8).

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
问题 dp实现 题目:书 有一书店引进了一套书,共有3卷,每卷书定价是60元,书店为了搞促销,推出一个活动,活动如下: 如果单独购其中一卷,那么可以打9.5折。 如果同时购两卷不同的,那么可以打9折。 如果同时购三卷不同的,那么可以打8.5折。 如果小明希望购第1卷x本,第2卷y本,第3卷z本,那么至少需要多少钱呢?(x、y、z为三个已知整数)。 1、过程为一次一次的购,每一次购也许只一本(这有三种方案),或者两本(这也有三种方案), 或者三本一起(这有一种方案),最后直到完所有需要的书。 2、最后一步我必然会在7种购方案中选择一种,因此我要在7种购方案中选择一个最佳情况。 3、子问题是,我选择了某个方案后,如何使得购剩余的书能用最少的钱?并且这个选择不会使得剩余的书为负数 。母问题和子问题都是给定三卷书的购量,求最少需要用的钱,所以有"子问题重叠",问题中三个购量设置为参数, 分别为i、j、k。 4、的确符合。 5、边界是一次购就可以完所有的书,处理方式请读者自己考虑。 6、每次选择最多有7种方案,并且不会同时实施其中多种,因此方案的选择互不影响,所以有"子问题独立"。 7、我可以用minMoney[i][j][k]来保存购第1卷i本,第2卷j本,第3卷k本时所需的最少金钱。 8、共有x * y * z个问题,每个问题面对7种选择,时间为:O( x * y * z * 7) = O( x * y* z )。 9、用函数MinMoney(i,j,k)来表示购第1卷i本,第2卷j本,第3卷k本时所需的最少金钱,那么有: MinMoney(i,j,k)=min(s1,s2,s3,s4,s5,s6,s7),其中s1,s2,s3,s4,s5,s6,s7分别为对应的7种方案使用的最少金钱: s1 = 60 * 0.95 + MinMoney(i-1,j,k) s2 = 60 * 0.95 + MinMoney(i,j-1,k) s3 = 60 * 0.95 + MinMoney(i,j,k-1) s4 = (60 + 60) * 0.9 + MinMoney(i-1,j-1,k) s5 = (60 + 60) * 0.9 + MinMoney(i-1,j,k-1) s6 = (60 + 60) * 0.9 + MinMoney(i-1,j,k-1) s7 = (60 + 60 + 60) * 0.85 + MinMoney(i-1,j-1,k-1)

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值