动态规划-状态机模型

news2024/9/28 15:32:08

大盗阿福

题目

链接:https://www.acwing.com/problem/content/1051/

阿福是一名经验丰富的大盗。趁着月黑风高,阿福打算今晚洗劫一条街上的店铺。

这条街上一共有 N N N 家店铺,每家店中都有一些现金。

阿福事先调查得知,只有当他同时洗劫了两家相邻的店铺时,街上的报警系统才会启动,然后警察就会蜂拥而至。

作为一向谨慎作案的大盗,阿福不愿意冒着被警察追捕的风险行窃。

他想知道,在不惊动警察的情况下,他今晚最多可以得到多少现金?

输入格式

输入的第一行是一个整数 T T T,表示一共有 T T T 组数据。

接下来的每组数据,第一行是一个整数 N N N ,表示一共有 N N N 家店铺。

第二行是 N N N 个被空格分开的正整数,表示每一家店铺中的现金数量。

每家店铺中的现金数量均不超过1000。

输出格式

对于每组数据,输出一行。

该行包含一个整数,表示阿福在不惊动警察的情况下可以得到的现金数量。

数据范围

1 ≤ T ≤ 50 1 \le T \le 50 1T50,
1 ≤ N ≤ 1 0 5 1 \le N \le 10^5 1N105

输入样例:

2
3
1 8 2
4
10 7 6 14

输出样例:

8
24

样例解释

对于第一组样例,阿福选择第2家店铺行窃,获得的现金数量为8。

对于第二组样例,阿福选择第1和4家店铺行窃,获得的现金数量为10+14=24。

思路-动态规划

动态规划:

  • 状态表示:f[i]表示前i家的最大收益

  • 状态计算:

    • 抢劫第i家店铺:f[i-2]+w[i]
    • 不抢劫第i家店铺:f[i-1]

代码

#include <bits/stdc++.h>

#define int long long
using namespace std;

void solve() {
    int n;
    cin >> n;
    vector<int> a(n + 1), f(n + 1);
    for (int i = 1; i <= n; i++) cin >> a[i];
    for (int i = 1; i <= n; i++) {
        f[i]= max(f[i-1],f[i-2]+a[i]);
    }
    cout<<f[n]<<endl;
}

signed main() {
#ifndef ONLINE_JUDGE
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    int t;
    cin >> t;
    while (t--) solve();
    return 0;
}

思路-状态机

状态机:

  • 状态表示:f[i,0],f[i,1]表示所有走了i步,且当前位于状态j的所有走法的集合的最大值

  • 状态计算:

    • 如果偷第i家,则第i-1家不能被偷:f[i,1]=f[i-1,0]+w[i]
    • 如果不偷第i家,则第i-1家任意安排:f[i,0]=max(f[i-1,1],f[i-1,0])
  • 最后结果为max(f[n][0],f[n][1])

状态机图:

image-20230519201339018

代码

#include <bits/stdc++.h>

#define int long long
using namespace std;


void solve() {
    int n;
    cin >> n;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; i++) cin >> a[i];
    vector<vector<int>> f(n + 1, vector<int>(2));
    f[1][0] = 0, f[1][1] = a[1];
    for (int i = 2; i <= n; i++) {
        f[i][0] = max(f[i - 1][1], f[i - 1][0]);
        f[i][1] = f[i - 1][0] + a[i];
    }
    cout<<max(f[n][0],f[n][1])<<endl;

}

signed main() {
#ifndef ONLINE_JUDGE
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    int t;
    cin >> t;
    while (t--) solve();
    return 0;
}

股票买卖 IV-k笔交易

题目

链接:https://www.acwing.com/problem/content/1059/

给定一个长度为 N N N 的数组,数组中的第 i i i 个数字表示一个给定股票在第 i i i 天的价格。

设计一个算法来计算你所能获取的最大利润,你最多可以完成 k k k 笔交易。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。一次买入卖出合为一笔交易。

输入格式

第一行包含整数 N N N k k k,表示数组的长度以及你可以完成的最大交易笔数。

第二行包含 N N N 个不超过 10000 10000 10000 的正整数,表示完整的数组。

输出格式

输出一个整数,表示最大利润。

数据范围

1 ≤ N ≤ 1 0 5 1 \le N \le 10^5 1N105,
1 ≤ k ≤ 100 1 \le k \le 100 1k100

输入样例1:

3 2
2 4 1

输出样例1:

2

输入样例2:

6 2
3 2 6 5 0 3

输出样例2:

7

样例解释

样例1:在第 1 天 (股票价格 = 2) 的时候买入,在第 2 天 (股票价格 = 4) 的时候卖出,这笔交易所能获得利润 = 4-2 = 2 。

样例2:在第 2 天 (股票价格 = 2) 的时候买入,在第 3 天 (股票价格 = 6) 的时候卖出, 这笔交易所能获得利润 = 6-2 = 4 。随后,在第 5 天 (股票价格 = 0) 的时候买入,在第 6 天 (股票价格 = 3) 的时候卖出, 这笔交易所能获得利润 = 3-0 = 3 。共计利润 4+3 = 7.

思路

状态机:

  • 状态表示:f[i,j,k]表示所有从前i个物品中选,进行了j次交易,且当前状态是k的所有选法的最大值

    • 当前持有股票【k=1】,当前没有股票【k=0】
    • 例如:f[i,j,0]表示前i天买卖了j次,当前手中无票,能获得的最大收益
    • f[i,j,1]表示前i天买卖进行了j次,当前手中有票,能获得的最大收益。
  • i天状态是持仓状态k=1),则第 i天可能产生的行为是 第i-1天买入行为 或 第i-1 天 持仓行为

    • f[i,j,1]=max(f[i-1,j,1],f[i-1,j-1,0]-w[i])
  • i 天状态是空仓状态(k=0),则第i天可能产生的行为是 第i-1天卖出行为 或 第i-1 空仓行为

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

注意边界问题:

边界的初值首先要明白变量的取值范围 i ∈ [ 1 , n ] , j ∈ [ 1 , k ] i\in[1,n],j\in[1,k] i[1,n],j[1,k],在边界之外的需要设置处置,例如第0天

第0天:f[0,j,0]=0,f[0,j,1]=-INF为什么设置为负无穷:因为第零天不可以持仓,这是一个非法的行为

第0笔:f[i,0,0]=0

如果问题求最大值,则可以把非法的赋值为负无穷,最小值同理

状态机模型:

image-20230519223911253

代码

#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 10;
int f[N][110][2];

int main() {
#ifndef ONLINE_JUDGE
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    int n, k;
    cin >> n >> k;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; i++) cin >> a[i];
    for (int i = 1; i <= k; i++) f[0][i][1] = -0x3f3f3f3f;
    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] + a[i]);//前一天空仓或者卖出
            f[i][j][1] = max(f[i - 1][j][1], f[i - 1][j - 1][0] - a[i]);
        }
    }
  	cout<<f[n][k][0]<<endl;
    return 0;
}

可以像01背包一样将空间优化掉一维:

image-20230519223833896

股票买卖V-冷冻期

题目

链接:https://www.acwing.com/problem/content/1060/

给定一个长度为 N N N 的数组,数组中的第 i i i 个数字表示一个给定股票在第 i i i 天的价格。

设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):

  • 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
  • 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 1 1 天)。

输入格式

第一行包含整数 N,表示数组长度。

第二行包含 N N N 个不超过 10000 10000 10000 的正整数,表示完整的数组。

输出格式

输出一个整数,表示最大利润。

数据范围

1 ≤ N ≤ 1 0 5 1 \le N \le 10^5 1N105

输入样例:

5
1 2 3 0 2

输出样例:

3

样例解释

对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出],第一笔交易可得利润 2-1 = 1,第二笔交易可得利润 2-0 = 2,共得利润 1+2 = 3。

思路

显然有三种状态:

f[i,1]表示第i天手中有票能获取的最大利润

f[i,0]表示卖出股票的第一天能获取的最大利润

f[i,2]表示卖出股票的第二天及以后能获取的最大利润

状态计算:

  • f[i,1]=max(f[i-1][1],f[i-1][2]-w[i])
  • f[i,0]=f[i-1][1]+w[i]
  • f[i,2]=max(f[i-1][0],f[i-1][2])

边界条件:

  • f[0][1]=-inf因为第0天不可能存在持有股票状态,因为前面没有天数可以买
  • f[0][0]=-inf因为第0天不可能是卖出股票的第一天
  • f[0][2]=0

状态机模型:

image-20230519225847438

代码

#include <bits/stdc++.h>

#define int long long
using namespace std;


signed main() {
#ifndef ONLINE_JUDGE
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    int n;
    cin >> n;
    vector<int> w(n + 1);
    for (int i = 1; i <= n; i++) cin >> w[i];
    vector<vector<int>> f(n + 1, vector<int>(3));

    f[0][1] = f[0][0] = -INT_MAX;
    for (int i = 1; i <= n; i++) {
        f[i][1] = max(f[i - 1][1], f[i - 1][2] - w[i]);
        f[i][0] = f[i - 1][1] + w[i];
        f[i][2] = max(f[i - 1][0], f[i - 1][2]);
    }
    cout<<max(f[n][0],f[n][2])<<endl;

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/546448.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

chatgpt赋能Python-python3_9怎么下载

Python 3.9: 从哪里下载以及如何安装 Python是一种高级编程语言&#xff0c;被广泛使用于数据科学、人工智能、Web开发等领域。Python的最新版本是Python 3.9&#xff0c;它带来了一些新的特性和改进。对于那些希望尝试Python 3.9的人来说&#xff0c;了解如何下载和安装是很重…

chatgpt赋能Python-python3下载文件

Python3下载文件&#xff1a;从入门到实践 在Python编程语言中&#xff0c;下载文件是一个常见的需求。无论你是想下载图片、视频、文本文件或者其他类型的文件&#xff0c;Python都提供了强大的工具来实现这一操作。在本文中&#xff0c;我们将深入探讨如何使用Python3来下载…

pwn入门(二)环境搭建

一.前言 在上一篇中介绍了一下pwn和一些前置知识&#xff0c;但是呢以我的感觉&#xff0c;我觉得ctf还是得多做题的&#xff0c;所以呢&#xff0c;我选择边做边学&#xff0c;我觉得这样可以快速熟悉pwn还可以有成就感。 这一篇就是搭建环境的分享&#xff0c;同时还有大佬告…

【问题记录】USB monitor抓包工具显示音频数据CRC error

一&#xff0c;简介 在进行UAC2.0调试的过程中&#xff0c;使用USB monitor抓包工具抓取音频流数据出现数据错乱现象&#xff0c;本文对该问题进行分析记录。 二&#xff0c;问题记录及分析过程 2.1 先看下正常的抓包数据是什么样子&#xff1a; 从上图可以看出&#xff0c;…

VMware ESXi 6.0 多网卡接入 多网段绑定 虚机接入不同网段

网卡要与对应网段的网络联通。不同的网卡接入不同网段的网络。要为vmware esxi 6 的多个虚机配置不同网段的ip地址&#xff0c;首先选择主机对应的网口分别插上处于在不同网段的网线。 配置管理网络 多个网口接入&#xff0c;只可以配置一个管理网络&#xff0c;就是只有一个网…

基于XGBOOST模型预测货物运输耗时 - Part 2 通过方差分析了解文本型变量与数值型目标变量的关系

在分析数据之前&#xff0c;我们需要剔除异常值的影响&#xff0c;也就是在某个分组情况下&#xff0c;标准差过大&#xff08;标准差越大&#xff0c;证明情况越不稳定&#xff09;&#xff0c;如果标准差比较小&#xff0c;就算是最小值和最大值差的比较大&#xff0c;我也认…

chatgpt赋能Python-python3下载numpy包

Python3 下载numpy包教程 如果你是一名Python开发者&#xff0c;那你一定不会陌生于NumPy。NumPy是Python中的一个科学计算库&#xff0c;它主要用来处理数组和矩阵运算。本文将会教你如何在Python3中下载NumPy库。 步骤一&#xff1a;确认你已经安装了pip 如果你使用的是Py…

chatgpt赋能Python-python3__2__3

Python323 - 一个强大的编程工具 介绍 Python323 是一种高级编程语言&#xff0c;最初由 Guido van Rossum 在 1989 年创建。Python 3.2.3 是 Python 3 的其中一个发行版&#xff0c;它拥有很多新特性和改进。Python323 可以运行在多种操作系统上&#xff0c;包括 Windows、L…

redis哨兵监控leader和master选举原理

当一个主从配置中的master失效后&#xff0c;sentinel可以选举出一个新的master,用于自动接替原master的工作&#xff0c;主从配置中的其他redis服务器自动指向新的master同步数据。是如何具体做的呢&#xff0c;主要有以下4步。 一般建议sentinel 采取奇数台. 1.SDown 主观下…

Day43【动态规划】1049.最后一块石头的重量 II、494.目标和、474.一和零

1049.最后一块石头的重量 II 力扣题目链接/文章讲解 视频讲解 还是需要转化为 0-1 背包问题&#xff1a;物品装入背包&#xff0c;求装入的最大价值&#xff08;每个物品至多装入一次&#xff09; 要把01背包问题套到本题上来&#xff0c;需要确定 背包容量物品价值物品重…

分布式消息中间件RocketMQ的应用

RocketMQ 应用 所有代码同步至GitCode&#xff1a;https://gitcode.net/ruozhuliufeng/test-rocketmq.git 普通消息 消息发送分类 ​ Producer对于消息的发送方式也有多种选择&#xff0c;不同的方式会产生不同的系统效果。 同步发送消息 ​ 同步发送消息是指&#xff0c;P…

Win11或Win10重置电脑提示“找不到恢复环境”

想要重置电脑缺提示找不到恢复环境 查看是否开启功能 按住“winx”选A管理员运行终端&#xff0c;输入reagentc /info。 如果信息结果如下&#xff1a; Windows RE 状态: DisabledWindows RE 位置:引导配置数据(BCD)标识符: cedd8faa-707a-11ed-ad72-a8056da9f4d6…

头歌计算机组成原理实验—运算器设计(3)第3关:4位快速加法器设计

第3关&#xff1a;4位快速加法器设计 实验目的 帮助学生掌握快速加法器中先行进位的原理&#xff0c;能利用相关知识设计4位先行进位电路&#xff0c;并利用设计的4位先行进位电路构造4位快速加法器&#xff0c;能分析对应电路的时间延迟。 视频讲解 实验内容 利用前一步设…

Learning C++ No.23【红黑树封装set和map】

引言 北京时间&#xff1a;2023/5/17/22:19&#xff0c;不知道是以前学的不够扎实&#xff0c;还是很久没有学习相关知识&#xff0c;对有的知识可以说是遗忘了许多&#xff0c;以该篇博客有关知识为例&#xff0c;我发现我对迭代器和模板的有关知识的理解还不够透彻&#xff…

音视频源码调试前准备vs2019+qt5.15.2搭建可调试环境

安装vs2019qt,并且在windows环境上安装ffmpeg&#xff0c;尝试使用qtcdb进行调试&#xff0c;尝试使用vs2019加载qt的程序。 安装VS20195.12.2qt环境&#xff0c;并进行测试。 1&#xff1a;安装Visual Studio 2019, a.从官网下载&#xff0c;或者vs2019社区版本下载地址 ht…

SNAP软件处理Sentinel-2 L2A数据为hdr或者tif文件

1.打开Sen2Cor插件处理好的或者下载好的L2A文件 若不知道如何将下载的L1C数据处理为L2A级数据可查看该篇博文 Sentinel-2数据下载及处理_dropoutgirl的博客-CSDN博客 在Bands文件夹下少了B10波段栅格文件: 这主要是因为波段10是卷云波段&#xff0c;需要的大气顶部&#xff0…

顺序表之线性表(难度:✨)

1.线性表 线性表呈现出一条线性&#xff0c;用指针把一块一块的内存连接起来。 其余还有树型结构&#xff0c;哈希结构&#xff0c;图结构。 线性表分为&#xff1a; 顺序表链表栈队列字符串 1.2顺序表 顺序表就是数组&#xff0c;但在数组的基础上&#xff0c;从头开始存。…

地下车库CO传感器报警系统

前言 在现代城市中&#xff0c;地下车库已经成为了不可或缺的交通设施。然而&#xff0c;在地下车库中&#xff0c;由于车辆尾气等因素&#xff0c;很容易出现CO中毒的风险&#xff0c;给车库内的人员带来威胁。本文将对地下车库CO传感器报警系统进行介绍和分析&#xff0c;包…

21级计科专业计算机组成原理实验考试(体验)

在使用VC6.0软件时&#xff0c;为了进入调试模式&#xff0c;需要先点击【Build】&#xff0c;再点击&#xff08; &#xff09; A. BuildExecute B. Go C. Execute D. Compile 在使用VC6.0软件进入调试模式后&#xff0c;点击【View】→【Debug Windows】后的&#xff08; &…

Shell脚本常见用法列举

前言 最近在复习shell脚本的相关知识&#xff0c;本文列举了一些在shell脚本中用得到的一些基础语法。 1&#xff1a;打印常见内部变量和环境变量值 shell中常用变量介绍 $0脚本名$n第n个参数&#xff0c;n1,2,3...$*所有参数列表&#xff08;视为一个整体&#xff0c;不包…