欢迎光临散文网 会员登陆 & 注册

423 线性DP 股票买卖K笔交易【动态规划】

2023-04-21 15:57 作者:零-雪鸦  | 我要投稿

// 空间优化

#include<iostream>

#include<cstring>

using namespace std;


const int N = 100010, M = 110;

int w[N], f[M][2];


int main() {

int n, k;

cin >> n >> k;

for (int i = 1; i <= n; i++) cin >> w[i];


for (int j = 0; j <= k; j++) f[j][1] = -1e6;


for (int i = 1; i <= n ; i++)

for (int j = 1; j <= k ; j++) {

f[j][1] = max(f[j][1], f[j - 1][0] - w[i]);

   f[j][0] = max(f[j][0], f[j][1] + w[i]);

}

cout << f[k][0];

}


#include<iostream>

#include<cstring>

using namespace std;


const int N = 100010, M = 110;

int w[N], f[N][M][2];


int main() {

int n, k;

cin >> n >> k;

for (int i = 1; i <= n; i++) cin >> w[i];


for (int j = 0; j <= k; j++) f[0][j][1] = -1e6;


for (int i = 1; i <= n; i++)

for (int j = 1; j <= k; j++) {

f[i][j][1] = max(f[i - 1][j][1], f[i - 1][j - 1][0] - w[i]);

f[i][j][0] = max(f[i - 1][j][0], f[i - 1][j][1] + w[i]);

}


cout << f[n][k][0];

}//三维保证正确





j++ 正序,先更新f[j][0]再更新f[j][1]

for (int j = 1; j <= k ; j++) {

  f[j][0] = max(f[j][0], f[j][1] + w[i]);

   f[j][1] = max(f[j][1], f[j - 1][0] - w[i]);\\交换顺序也是正确


f[j][0] = max(f[j][0], f[j][1] + w[i]); f[j][0]相当于f[i-1][j][0],f[j][1] + w[i]相当于f[i-1][j][1] + w[i]

f[i][j][0] = max(f[i - 1][j][0], f[i - 1][j][1] + w[i]);// 原代码

f[j][0] = max(f[i-1][j][0], f[i-1][j][1] + w[i]);// 实际代码与原代码等价


f[j][1] = max(f[j][1], f[j - 1][0] - w[i]);f[j][1]相当于f[i-1][j][1],f[j - 1][0] - w[i]相当于f[i][j - 1][0] - w[i]


f[i][j][1] = max(f[i - 1][j][1], f[i - 1][j - 1][0] - w[i]);原代码

f[i][j][1] = max(f[i - 1][j][1], f[i][j - 1][0] - w[i]);滚动数组等价代码,滚动数组的更新有些数偏大

f[i][j - 1][0] - w[i]必然大于等于f[i - 1][j - 1][0] - w[i]


f[j][0]更新正确,f[j][1]更新错误



j++ 正序,先更新f[j][1]再更新f[j][0]

for (int j = 1; j <= k ; j++) {

f[j][1] = max(f[j][1], f[j - 1][0] - w[i]);\\交换顺序也是正确

  f[j][0] = max(f[j][0], f[j][1] + w[i]);

f[j][1] = max(f[j][1], f[j - 1][0] - w[i]);f[j][1];f[j][1]存的是旧值f[i - 1][j][1], f[j - 1][0] - w[i] 存储f[i][j - 1][0] - w[i];


f[i][j][1] = max(f[i - 1][j][1], f[i - 1][j - 1][0] - w[i]);//原代码

f[j][1] = max(f[i - 1][j][1],f[i][j - 1][0] - w[i]) //滚动数组某些值必然偏大更新

f[j][0] = max(f[j][0], f[j][1] + w[i]); f[j][1]相当于f[i-1][j][0],f[j][1] + w[i]相当于 max(f[i - 1][j][1]+w[i],f[i][j - 1][0])


f[i][j][0] = max(f[i-1][j][0], f[i-1][j][1] + w[i]); // 原代码

f[j][0] = max( f[i-1][j][0], f[i-1][j][1]+w[i],f[i][j - 1][0])// 按理说大于等于原代码才行

多了个这玩意f[i][j - 1][0]


f[i][j][0]  前i天,交易了j笔,手头无票 肯定大于 前i天,交易了j-1笔,手头无票 

max(f[i-1][j][0], f[i-1][j][1]+w[i])>= f[i][j - 1][0]


f[j][1]更新错误,f[j][0]更新正确


如果这个可行,就保证了正确性f[j][0]

 



是什么保证了滚动数组的正确性,不光是正序还是逆序,更新位置交换也一样



j-- 逆序,先更新f[j][0]再更新f[j][1]

for (int j = k; j >=1 ; j--) {  

  f[j][0] = max(f[j][0], f[j][1] + w[i]);

f[j][1] = max(f[j][1], f[j - 1][0] - w[i]);

}


f[j][0] = max(f[j][0], f[j][1] + w[i]); f[j][0]存的是旧值f[i - 1][j][0],f[j][1] + w[i]存的是f[i-1][j][1] + w[i]

f[i][j][0] = max(f[i - 1][j][0], f[i - 1][j][1] + w[i]); //原代码

f[j][0] = max(f[i - 1][j][0], f[i-1][j][1] + w[i]);实际代码与原代码等价


f[j][1] = max(f[j][1], f[j - 1][0] - w[i]);f[j][1]存的是旧值f[i-1][j][1],f[j - 1][0] - w[i] 存的是 f[i-1][j - 1][0] - w[i]

f[i][j][1] = max(f[i - 1][j][1], f[i - 1][j - 1][0] - w[i]);// 原代码

f[j][1] = max(f[i-1][j][1], f[i-1][j - 1][0] - w[i])// 实际代码与原代码等价


f[j][0]、f[j][1]都更新正确



j-- 逆序,先更新f[j][1]再更新f[j][0]

f[j][1] = max(f[j][1], f[j - 1][0] - w[i]);

f[j][0] = max(f[j][0], f[j][1] + w[i]);


f[j][1] = max(f[j][1], f[j - 1][0] - w[i]);f[j][1]存的是旧值f[i-1][j][1],f[j - 1][0] - w[i] 存的是 f[i-1][j - 1][0] - w[i]

f[i][j][1] = max(f[i - 1][j][1], f[i - 1][j - 1][0] - w[i]);// 原代码

f[j][1] = max(f[i-1][j][1], f[i-1][j - 1][0] - w[i])// 实际代码与原代码等价


f[j][0] = max(f[j][0], f[j][1] + w[i]);f[j][0]存的是旧值f[i - 1][j][0],f[j][1] + w[i]存的是max(f[i-1][j][1]+ w[i], f[i-1][j - 1][0])

f[j][0] = max(f[i - 1][j][0], f[i-1][j][1]+ w[i], f[i-1][j - 1][0]);

更新f[j][0]就是更新f[i][j][0] ,也是多了一个这玩意 f[i-1][j - 1][0] , max(f[i - 1][j][0], f[i-1][j][1]+ w[i])>= f[i-1][j - 1][0]


f[j][1]正确,f[j][0]正确


423 线性DP 股票买卖K笔交易【动态规划】的评论 (共 条)

分享到微博请遵守国家法律