动态规划之状态机

大盗阿福

大盗阿福

状态机
在这里插入图片描述

算法思路:

//状态表示:
//      f[i]表示抢劫前i家店铺的收益
//状态计算    
//      抢第i家:  f[i - 2] + w[i]
//      不抢第i家:f[i - 1]
//状态分解:
//  f[i] = 0:未选最后一个店铺
//  f[i] = 1:选择最后一个店铺

//

//状态表示:
//      f[i][j]:所有走了i步,且当前位于状态j的所有走法
//属性:
//      max
//状态计算:
//      f[i][0]:    最后一步0->0    |       最后一步1->0
//                  f[i - 1][0]       |       f[i-1][1]
//      f[i][1]:    最后一步0->1
//                  f[i - 1][0] + w[i]
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 100010, INF = 0x3f3f3f;

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

int main(){
    int T;
    cin >> T;
    while(T --){
        cin >> n;
        for(int i = 1; i <= n; i ++) cin >> w[i];
        
        //状态机入口:从0开始,不能取到1
        f[0][0] = 0, f[0][1] = -INF;
        
        for(int i = 1; i <= n; i ++){
            f[i][0] = max(f[i - 1][0], f[i - 1][1]);
            f[i][1] = f[i - 1][0] + w[i];
        }
        
        cout << max(f[n][0], f[n][1]) << endl;
    }
    return 0;
}

股票买卖IV

股票IV状态机

状态机模型
在这里插入图片描述

//两种状态:
//      k = 0: 手中无货
//      k = 1:手中有货

//状态表示:f[i][j][k]:代表交易了i天,已经交易了j次,状态为k

//属性:max

//状态计算:
//      f[i][j][0]:    最后一步 0 -> 0 |    最后一步 1 -> 0
//                      f[i - 1][j][0] |    f[i - 1][j][1] + w[i]
//
//      f[i][j][1]:    最后一步 1 -> 1 |   最后一步 0 -> 1
//                      f[i - 1][j][1] |    f[i - 1][j - 1][0] - w[i]

//理解:
//  1->0:表示 手中有货 变为 手中无货,并且当前正在进行交易,还未交易完成,只有将w[i]加上才能够算交易完成
//  0->1:j表示正在进行第j次交易,当前正在交易的钱f[i][j][1] 等于 尚未交易的钱 减去 购买的钱
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;

const int N = 100010, M = 110, INF = 0x3f3f3f;
int n, k;
int f[N][M][2];
int w[N];

int main(){
    cin >> n >> k;
    for(int i = 1; i <= n; i ++) cin >> w[i];
    
    //初始化
    memset(f, -INF, sizeof f);
    for(int i = 0; i <= n; i ++) f[i][0][0] = 0;
    
    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]);
        }
    
    int res = 0;
    for(int i = 1; i <= k; i ++) res = max(res, f[n][i][0]);
    
    cout << res << endl;
    return 0;
}

股票买卖V

股票买卖V

股票买卖自动机

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9CfBFqGT-1647612492857)(./pic/%E8%82%A1%E7%A5%A8%E4%B9%B0%E5%8D%96V.png)]

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;

const int N = 100010;
int f[N][3];
int n;
int w[N];

int main(){
    cin >> n;
    for(int i = 1; i <= n; i ++) cin >> w[i];
    
    memset(f, -0x3f3f3f, sizeof f);
    f[0][2] = 0;
    for(int i = 1; i <= n; i ++){
        f[i][0] = max(f[i - 1][0], f[i - 1][2] - w[i]);
        f[i][1] = f[i - 1][0] + w[i];
        f[i][2] = max(f[i - 1][1], f[i - 1][2]);
    }
    
    cout << max(f[n][1], f[n][2]) << endl;
    
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值