K次交易股票最大利润(动态规划)

一.问题背景

1.在给定的n天股票价格中,在最多进行k次交易下的最大利润。

2.每次交易为买入和卖出一个周期(不允许在卖出前买入)。

算法目的: 若给定股票每日股价序列price={n₁,n₂,n₃···n_(m)},要求在指定交易次数下k下,求得最大利润。

二.动态规划

在这里插入图片描述

问题结构分析

(1)给出问题表示

profit[i][j]:表示进行 i 次交易在第 j 天所能获得的最大利润,在每次卖出后更新。

(2)明确原始问题

profit[k][n-1]:在k次交易下利润的最大值。

递归关系建立

交易行为分为买入,不卖出和卖出:

买入的情况:

当确定卖出后能够实现更大利润的时候才确定是否购买。

不卖出的情况:

不交易利润与前一天相同,便有:profit[i][j]=profit[i][j-1]。

买入卖出的情况:

如果在第 n天卖出股票,则需要找出之前某一天 j (0<=j<n)买入

股票,此笔交易的利润为price[n]-price[j-1]。

再加上在第 j 天之前进行的第i-1次交易所获得的最大利润,即

profit[i-1][j-1]。为保证利润最大需使profit[i - 1][j - 1] - price[j-1]最大

因此第 n 天卖出获得的最大利润为price[n]+profit[i-1][j-1]-price[j-1],可写为price[n]+max(profit[i-1][j-1]-price[j])(0<=j<n)。

综合三种情况:

profit[i][n]=max(profit[i][n-1],price[n]+max(profit[i-1][j-1]-price[j-1]))

为了方便计算,我们引入了prevDiff来存储 profit[i-1][j-1]-price[j-1] 的最大值,即prevDiff=max(prevDiff, profit[i−1][j−1]−price[j-1])。

经过替换为 i,j 则有: profit[i][j]=max(profit[i][j−1],price[j]+prevDiff)。

状态表示

(1)profit[i][j]为原问题的子问题。

(2)子问题通过i(第几次交易)和j(第几天)两个参数来确定。

(3)profit[i][j]表示最多进行i次交易在第j天的最大利润。

(4)profit[k][n-1]为原问题的最大利润。

状态递归方程

(1)当i=0或j=0时,profit[i][j]=0

(2)当i,j>0时,profit[i][j]分为两种情况:

①当不交易时,profit[i][j]=profit[i][j-1]))。
②当发生交易时,profit[i][j]=max(profit[i][j-1],profit[j]+prevDiff)(prevDiff=max(prevDiff,profit[i-1][j-1]))。

自底向上计算

 

初始化

profit[i][0]=profit[0][j]=0 (前者代表天数为0如果只有一天,不管允许多少次交易,利润都是 0,因为没有足够的时间进行买卖;后者表示如果没有交易,即使有 i 天,利润也是 0 )。

递推公式

prevDiff=max(prevDiff,profit[i−1][j−1]−price[j−1] )
profit[i][j] = max(profit[i][j−1],price[j]+prevDiff)

填表

price={1,3,7,4,8,2,7}

0 1 2 3 4 5 6
0 0 0 0 0 0 0 0
1 0 2 6 6 7 7 7
2 0 2 6 6 10 10 12
3 0 2 6 6 10 10 15
  1. 这里以填profit[1][1]为例:

prevDiff= max(prevDiff,profit[0][0]−price[0] )=max(-∞,-1)= -1
profit[1][1]=max(profit[1][0],price[1]+prevDiff)=max(0,2)=2

  1. 这里以填profit[1][2]为例:

prevDiff= max(prevDiff,profit[0][1]−price[1] )=max(-1,-3)= -1
profit[1][2]=max(profit[1][1],price[2]+prevDiff)=max(2,6)=6

  1. 这里以填profit[2][1]为例:

prevDiff= max(prevDiff,profit[1][0]−price[0] )=max(-∞,-1)= -1
profit[2][1]=max(profit[2][0],price[1]+prevDiff)=max(0,2)=2

  1. 当填到profit[k][n-1]得到最大利润

 

最优追踪方案

 

  1. 找到最后卖出点

if (profit[v][b] != profit[v][b - 1]) 说明在第b天卖出了股票,反之则进行b-- 操作,知道找到最后卖出点(此时v=k,b=n-1),从后往前追溯。

  1. 找到相应的买入点

if (profit[v - 1][i] - price[i] == profit[v][b] - price[b])由总利润-售出价格=买入后,卖出前的利润。应等于上次利润-买入成本。若不等则i–往前比较。循环操作(1)和操作(2)直到v或b<=0便可完成全追溯过程

  1. 例如:横坐标为j,纵坐标为i

price={1,3,7,4,8,2,7}

0 1 2 3 4 5 6
0 0 0 0 0 0 0 0
1 0 2 6 6 7 7 7
2 0 2 6 6 10</
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值