洛谷P2569[SCOI2010]股票交易题解

本文探讨了在特定交易规则下,如何使用动态规划和单调队列优化股票交易策略,以实现收益最大化。通过分析不同交易场景,如买入、卖出和不交易的情况,详细解释了状态转移方程,并给出了具体代码实现。

题目链接

分析:

f i , j f_{i,j} fi,j表示第 i i i天后拥有 j j j张股票时最多能赚的钱数

显然,对于所有 f i , j f_{i,j} fi,j,转移时共有三种情况

1、不做交易

直接由上一天转移:

f i , j = f i , j f_{i,j} = f_{i,j} fi,j=fi,j

2、买入

由于每 w w w天才能交易一次,所以应从第 i − w − 1 i - w - 1 iw1天及以前更新,又第 i − w − 1 i - w - 1 iw1天前的信息都会更新到第 i − w − 1 i - w - 1 iw1天上,所以转移时需考虑第 i − w − 1 i - w - 1 iw1天。然后再枚举交易前拥有股票数 k k k,因为第 i i i天最多购买 a p i ap_i api股,所以 k k k的枚举范围是 [ m i n ( j − a s i , 0 ) , j ) [min(j - as_i,0),j) [min(jasi,0),j),所以转移方程为:

f i , j = max ⁡ k = m a x ( j − a s i , 0 ) j − 1 { f i − w − 1 , k − ( j − k ) a p i } f_{i,j} = \max_{k = max(j - as_i,0)}^{j - 1}\{f_{i - w - 1,k} - (j - k)ap_i\} fi,j=k=max(jasi,0)maxj1{fiw1,k(jk)api}

考虑优化这个柿子,注意到

f i − w − 1 , k − ( j − k ) a p i = f i − w − 1 , k + k ⋅ a p i − j ⋅ a p i f_{i - w - 1,k} - (j - k)ap_i = f_{i - w - 1,k} + k \cdot ap_i - j\cdot ap_i fiw1,k(jk)api=fiw1,k+kapijapi

j ∗ a p i j * ap_i japi为定值,可以提出到大括号外,所以原柿化为:

f i , j = max ⁡ k = m a x ( j − a s i , 0 ) j − 1 { f i − w − 1 , k + k ⋅ a p i } − j ⋅ a p i f_{i,j} = \max_{k = max(j - as_i,0)}^{j - 1}\{f_{i - w - 1,k} + k\cdot ap_i\} - j\cdot ap_i fi,j=k=max(jasi,0)maxj1{fiw1,k+kapi}japi

观察大括号中的柿子,显然可以单调队列优化

3、卖出

类似于情况2,有:

f i , j = max ⁡ k = j + 1 m i n ( j + b s i , m ) { f i − w − 1 , k + ( k − j ) b p i } f_{i,j} = \max_{k = j + 1}^{min(j + bs_i,m)}\{f_{i - w - 1,k} + (k - j)bp_i\} fi,j=k=j+1maxmin(j+bsi,m){fiw1,k+(kj)bpi}

f i , j = max ⁡ k = j + 1 m i n ( j + b s i , m ) { f i − w − 1 , k + k ⋅ b p i } − j ⋅ b p i f_{i,j} = \max_{k = j + 1}^{min(j + bs_i,m)}\{f_{i - w - 1,k} + k \cdot bp_i\} - j \cdot bp_i fi,j=k=j+1maxmin(j+bsi,m){fiw1,k+kbpi}jbpi

显然也可以单调队列优化

取三种情况的最大值即可

Code:

#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 2050,inf = 1e9;
int n,m,w,as,bs,ap,bp,l,r,from,ans,f[maxn][maxn],q[maxn];
int read(){
    int x = 0;
    char c = getchar();
    while(c < '0' || c > '9') c = getchar();
    while(c >= '0' && c <= '9') x = x * 10 + (c ^ 48),c = getchar();
    return x;
}
int main(){
    n = read(),m = read(),w = read();
    for(int i = 0; i <= n; i ++)
        for(int j = 0; j <= m; j ++)
            f[i][j] = -inf;
    f[0][0] = 0;
    for(int i = 1; i <= n; i ++){
        ap = read(),bp = read(),as = read(),bs = read();
        //不做交易
        for(int j = 0; j <= m; j ++) f[i][j] = max(f[i][j],f[i - 1][j]);
        from = max(0,i - w - 1);//i - k - 1 < 0 时,i不足w天,只能从0(还未交易过)转移
        //买入
        l = 1,r = 0;
        for(int j = 0; j <= m; j ++){
            while(l <= r && q[l] < j - as) l ++;
            while(l <= r && f[from][q[r]] + q[r] * ap < f[from][j] + j * ap) r --;
            r ++,q[r] = j,f[i][j] = max(f[i][j],f[from][q[l]] + (q[l] - j) * ap);
        	//单调队列优化(伪)模板
        }
        //卖出
        l = 1,r = 0;
        for(int j = m; j >= 0; j --){//卖出时应倒序枚举
            while(l <= r && q[l] > j + bs) l ++;
            while(l <= r && f[from][q[r]] + q[r] * bp < f[from][j] + j * bp) r --;
            r ++,q[r] = j,f[i][j] = max(f[i][j],f[from][q[l]] + (q[l] - j) * bp);
        }
    }
    cout << f[n][0] << endl;
    return 0;
}

"Mstar Bin Tool"是一款专门针对Mstar系列芯片开发的固件处理软件,主要用于智能电视及相关电子设备的系统维护与深度定制。该工具包特别标注了"LETV USB SCRIPT"模块,表明其对乐视品牌设备具有兼容性,能够通过USB通信协议执行固件读写操作。作为一款专业的固件编辑器,它允许技术人员对Mstar芯片的底层二进制文件进行解析、修改与重构,从而实现系统功能的调整、性能优化或故障修复。 工具包中的核心组件包括固件编译环境、设备通信脚本、操作界面及技术文档等。其中"letv_usb_script"是一套针对乐视设备的自动化操作程序,可指导用户完成固件烧录全过程。而"mstar_bin"模块则专门处理芯片的二进制数据文件,支持固件版本的升级、降级或个性化定制。工具采用7-Zip压缩格式封装,用户需先使用解压软件提取文件内容。 操作前需确认目标设备采用Mstar芯片架构并具备完好的USB接口。建议预先备份设备原始固件作为恢复保障。通过编辑器修改固件参数时,可调整系统配置、增删功能模块或修复已知缺陷。执行刷机操作时需严格遵循脚本指示的步骤顺序,保持设备供电稳定,避免中断导致硬件损坏。该工具适用于具备嵌入式系统知识的开发人员或高级用户,在进行设备定制化开发、系统调试或维护修复时使用。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值