zoukankan      html  css  js  c++  java
  • AcWing 1057. 股票买卖 IV

    题目传送门

    一、画图分析状态机

    二、状态机分析法

    闫式DP分析法--状态机分析法

    • 集合
      \(f[i,j,0]\):只考虑前\(i\)天,且已经进行完\(j-1\)次交易,正在进行第\(j\)次交易,且手中无货的所有购买方式的集合。
      \(f[i,j,1]\):只考虑前\(i\)天,且已经进行完\(j-1\)次交易,正在进行第\(j\)次交易,且手中有货的所有购买方式的集合。

    • 属性:最大值

    • 状态计算
      根据状态机的图来进行分析写出:

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

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

    【注】:卖出行为 会构成一次完整的交易,所以进行该类转移时, j 的参数也要变动

    时间复杂度: \(O(N×K)\)
    空间复杂度: \(O(N×K)\)
    初始状态: \(f(0,0,0)\)
    目标状态: \(f(n,j,0)\)其中\(0≤j≤k\)

    三、实现代码[朴素版本]

    #include <bits/stdc++.h>
    
    using namespace std;
    const int N = 100010;
    const int M = 110;
    int n;          //n天
    int k;          //可以完成的最大交易数量
    int w[N];       //每一天的股票价格
    
    int f[N][M][2];
    
    int main() {
        cin >> n >> k;
        for (int i = 1; i <= n; i++) cin >> w[i];//读入每一天的股票价格
    
        //不合法状态初始化成-INF(求最大值更新为—INF,求最小值更新成INF)
        memset(f, -0x3f, sizeof f);
        //前i天交易,交易完成次数为0,手中无股票的状态全为0
        for (int i = 0; i <= n; i++) f[i][0][0] = 0;
    
        //dp
        for (int i = 1; i <= n; i++) //遍历每一天
            for (int j = 1; j <= k; j++) { //遍历每一个可以完成的最大交易数量
                f[i][j][0] = max(f[i - 1][j][0], f[i - 1][j][1] + w[i]);
                f[i][j][1] = max(f[i - 1][j][1], f[i - 1][j - 1][0] - w[i]);
            }
        //我们发现买入不卖一定不是最优解,所以不用枚举f[i][j][1]的状态
        int res = 0;
        for (int i = 0; i <= k; i++) res = max(res, f[n][i][0]);
        //输出
        printf("%d\n", res);
        return 0;
    }
    

    四、滚动数组优化

    #include <bits/stdc++.h>
    
    using namespace std;
    const int N = 100010;
    const int M = 110;
    int n;          //n天
    int k;          //可以完成的最大交易数量
    int w[N];       //每一天的股票价格
    
    int f[2][M][2];
    
    int main() {
        cin >> n >> k;
        for (int i = 1; i <= n; i++) cin >> w[i];//读入每一天的股票价格
    
        //不合法状态初始化成-INF(求最大值更新为—INF,求最小值更新成INF)
        memset(f, -0x3f, sizeof f);
        //前i天交易,交易完成次数为0,手中无股票的状态全为0
        for (int i = 0; i <= n; i++) f[i & 1][0][0] = 0;
        //等价于f[1][0][0]=f[0][0][0]=0
    
        //dp
        for (int i = 1; i <= n; i++) //遍历每一天
            for (int j = 1; j <= k; j++) { //遍历每一个可以完成的最大交易数量
                f[i & 1][j][0] = max(f[i - 1 & 1][j][0], f[i - 1 & 1][j][1] + w[i]);
                f[i & 1][j][1] = max(f[i - 1 & 1][j][1], f[i - 1 & 1][j - 1][0] - w[i]);
            }
        //我们发现买入不卖一定不是最优解,所以不用枚举f[i][j][1]的状态
        int res = 0;
        for (int i = 0; i <= k; i++) res = max(res, f[n & 1][i][0]);
        //输出
        printf("%d\n", res);
        return 0;
    }
    
  • 相关阅读:
    美女程序员是如何将QQ转换成题目中那串数字的--读博文《找女神要QQ号码》
    C#微信开发-微信JS-SDK(1)之通过config接口注入权限验证配置
    AjaxUpload.3.5.js之ASP.NET 文件上传
    web开发常用的js验证,利用正则表达式验证邮箱、手机、身份证等输入
    HNU_结对项目_小初高数学学习软件_功能说明
    转载:alpha测试和beta测试的区别;黑盒测试和白盒测试的区别;
    HNU_个人项目_中小学数学卷子自动生成程序_简要分析HnuLyx代码
    文件与磁盘空间管理---外存分配方式、存储空间管理
    Java程序设计——不一样的开始 IP地址判定
    Java编程思想—八皇后问题(数组法、堆栈法)
  • 原文地址:https://www.cnblogs.com/littlehb/p/15734903.html
Copyright © 2011-2022 走看看