ACM - DP - 提高2 (状态机 + 状态压缩 + 区间 + 树形 + 数位 + 单调队列优化 + 斜率优化)

news2024/11/17 9:51:16

DP 类型题二

  • 【跳转DP 类型题一 (模型:数字三角形+最长上升子序列+背包】
  • 一、状态机模型
    • 1、AcWing 1057. 股票买卖 IV :两个状态转换
    • 2、AcWing 1058. 股票买卖 V :三个状态转换
    • 3、AcWing 1052. 设计密码 :T 维状态转换
  • 二、状态压缩DP
    • 1、AcWing 1064. 小国王 :九宫格限制
    • 2、AcWing 292. 炮兵阵地 :十字限制
    • 3、
  • 三、区间DP
  • 四、树形DP
  • 五、数位DP
  • 六、单调队列优化DP
  • 七、斜率优化DP

【跳转DP 类型题一 (模型:数字三角形+最长上升子序列+背包】

!!!传送门~~~~~~~~~~~~~~~~

一、状态机模型

1、AcWing 1057. 股票买卖 IV :两个状态转换

原题链接:https://www.acwing.com/problem/content/description/1059/
在这里插入图片描述

/*
dp[i][j][0] 表示在前 i 天中,恰好使用 j 次交易机会,且目前没有持有股票的最大收益。
dp[i][j][1] 表示在前 i 天中,恰好使用 j 次交易机会,且目前持有股票的最大收益。
*/
#include<iostream>
#include<cstring>

using namespace std;

int dp[100010][110][2];

int main() {
    int n, k;
    cin >> n >> k;
     //除了dp[i][0][0], 其他诸如dp[x][0][1]、dp[0][x][0/1]是不合法的
    memset(dp, -0x3f, sizeof dp);
    for (int i = 0; i <= n; ++ i) dp[i][0][0] = 0;
    
    int ans = 0;
    for (int i = 1; i <= n; ++ i) {
        int a;
        cin >> a;
        for (int j = 1; j <= k; ++ j) {
            // dp[i][j][0] = max(前一天也没有持股,前一天持股今天抛售);
            dp[i][j][0] = max(dp[i - 1][j][0], dp[i - 1][j][1] + a);
            // dp[i][j][0] = max(前一天也持股,前一天没有持股今天买入);
            dp[i][j][1] = max(dp[i - 1][j][1], dp[i - 1][j - 1][0] - a);
            //因为不一定要把k次机会全部用完,所以需要对过程取max
            ans = max(ans, dp[i][j][0]);  
        }
    }
    cout << ans;
    return 0;
}

2、AcWing 1058. 股票买卖 V :三个状态转换

原题链接:https://www.acwing.com/problem/content/1060/
在这里插入图片描述
【图解】
在这里插入图片描述
【代码】

#include<iostream>
#include<cstring>

using namespace std;

// dp[i][0] 表示前 i 天中,第 i 天持股的最大收益
// dp[i][1] 表示前 i 天中,第 i 天是冷却期的最大收益
// dp[i][2] 表示前 i 天中,第 i 天是非冷却期却没有持股的最大收益
int dp[100010][3];

int main() {
    int n;
    cin >> n;
    dp[0][0] = dp[0][1] = -0x3f3f3f3f;
    for (int i = 1; i <= n; ++ i) {
        int a;
        cin >> a;
        // dp[i][0] = max(继续持股,第i天买入);
        dp[i][0] = max(dp[i - 1][0], dp[i - 1][2] - a);
        // dp[i][1] = 第 i 天卖出
        dp[i][1] = dp[i - 1][0] + a;
        // dp[i][0] = max(前一天不是冷却期不持股保持今天不持股,前一天是冷却期保持今天不持股,);
        dp[i][2] = max(dp[i - 1][2], dp[i - 1][1]);
    }
    cout << max(dp[n][1], dp[n][2]);
    return 0;
}

3、AcWing 1052. 设计密码 :T 维状态转换

原题链接:https://www.acwing.com/problem/content/description/1054/
在这里插入图片描述
在这里插入图片描述

#include<iostream>
#include<cstring>

using namespace std;

const int N = 60;
const int modd = 1e9 + 7;

// dp[i][j] 表示密码后 i 个字符和子串 t 前 j 个字符相等的最大方案数
// 此时第 i + 1 位若与 j + 1 位相等,那么明显 dp[i + 1][j + 1] += dp[i][j];
// 若不相等,则按照kmp匹配那样找到能将两个字符对齐的 j

//其中dp[i][j] 中,若 i < j 是不合法的,但不必特判
//例如dp[2][5],一定有dp[2][5] = dp[0][3] = 0。


int dp[N][N], ne[N];
char s[N];

int main() {
    int n;
    cin >> n >> s + 1;
    int m = strlen(s + 1);
    for (int i = 2, j = 0; i <= m; ++ i) {
        while (j && s[i] != s[j + 1]) j = ne[j];
        if (s[i] == s[j + 1]) ++ j;
        ne[i] = j;
    }
    dp[0][0] = 1;
    //密码已经配备了前i个字母
    for (int i = 0; i < n; ++ i) {
        //密码前i个字母中长度为j的后缀 == 子串t中长度为j的前缀
        for (int j = 0; j < m; ++ j) {
            //此时密码要配对的下一位字母是k
            for (int k = 'a'; k <= 'z'; ++ k) {
                int jj = j;   //因为看漏了这一步 卡了一周才明白……
                while (jj && k != s[jj + 1]) jj = ne[jj];
                if (k == s[jj + 1]) ++ jj;
                if (jj < m) dp[i + 1][jj] = (dp[i + 1][jj] + dp[i][j]) % modd;
            }
        }
    }
    long long ans = 0;
    for (int i = 0; i < m; ++ i) ans = (ans + dp[n][i]) % modd;
    cout << ans << endl;
    return 0;
}

二、状态压缩DP

1、AcWing 1064. 小国王 :九宫格限制

原题链接:https://www.acwing.com/problem/content/description/1066/
在这里插入图片描述
思路
在这里插入图片描述
代码

#include<iostream>
#include<vector>

using namespace std;

const int N = 15, M = 110;

//dp[i][j][u] 表示前 i 行中一共安排了 j 个国王,同时最后一行的摆放方式是二进制的state[u](1-有国王,0-无国王)
long long dp[N][M][300];
//state存下所有不存在相邻1的数
//cnt[i] = state[i]二进制中 1 的个数
vector<int> state, cnt;
int n, m;

//判断a是否合法:存在相邻的1 - false
bool check(int a) {
	for (int i = 0; i < n; ++ i) {
		if ((a >> i) & 1 && (a >> (i + 1)) & 1)
			return false;
	}
	return true;
}

//计算 a 的二进制中有多少个 1
int count(int a) {
	int ans = 0;
	for (int i = 0; i < n; ++ i) {
		if ((a >> i) & 1) ++ ans;
	}
	return ans;
}

int main() {
	cin >> n >> m;
	//预处理
	for (int i = 0; i < 1 << n; ++ i) {
		if (check(i)) {
			state.push_back(i);
			cnt.push_back(count(i));
		}
	}
	//初始化
	dp[0][0][0] = 1;
	//前 i 行棋盘(多处理1行方便后面输出答案)
	for (int i = 1; i <= n + 1; ++ i) {
	    // 前 i 行棋盘一共用了多少个国王
		for (int j = 0; j <= m; ++ j) {
		    // 第 i - 1 行国王摆放情况
			for (int k = 0; k < state.size(); ++ k) {
			    // 第 i 行国王摆放情况
				for (int u = 0; u < state.size(); ++ u) {
			        int a = state[k], b = state[u];
			        // 数量合法
				    if (cnt[u] <= j) {
				        // if ( a[i]和b[i]不同时为1 && a[i]和b[i-1]、b[i+1]不同时为1 )
				        if (!(a & b) && check(a | b)) {
				            dp[i][j][u] += dp[i - 1][j - cnt[u]][k];
				        }
				    }
				}
			}
		}
	}
	cout << dp[n + 1][m][0];
	return 0;
}

2、AcWing 292. 炮兵阵地 :十字限制

原题链接:https://www.acwing.com/problem/content/description/294/
在这里插入图片描述
在这里插入图片描述

// 这道题主要是一开始只用了两维去表示,dp[i][j]表示处理前 i 行且最后一行状态时state[j].
// 但很明显在状态转移时,dp[i - 1][k] 和 dp[i - 2][u] 即便j、k、u这三行是合法的,
// 但是对于 dp[i - 1][k] 所表示方案中的第 i - 3 行不一定不会和 dp[i - 2][u] 中的第 i - 3 行矛盾。
// 所以需要再增加一维,使得状态转移时所表示的方案是一一对应的。

#include<iostream>
#include<vector>

using namespace std;

const int N = 110, M = 70;

// dp[i][j][k]表示处理前 i 行,第i - 1行状态是state[j]、第 i 行状态是state[k]
int dp[2][M][M];
vector<int> state, cnt;
int book[N];  //二进制表示地图,1 - H,0 - P
int n, m;

//判断状态是否合法:两个1之间距离小于2 - false
bool check(int a) {
    for (int i = 0; i < m; ++ i) {
        if (((a >> i) & 1) && (((a >> (i + 1)) & 1) || ((a >> (i + 2)) & 1))) return false;
    }
    return true;
}

//计算a中有多少个1
int count(int a) {
    int res = 0;
    for (int i = 0; i < m; ++ i) {
        if ((a >> i) & 1) ++ res;
    }
    return res;
}

int main() {
    cin >> n >> m;
    char c;
    //预处理地图
    for (int i = 1; i <= n; ++ i) {
        for (int j = m - 1; j >= 0; -- j) {
            cin >> c;
            if (c == 'H') book[i] += 1 << j;
        }
    }
    //预处理出在水平方向上合法的状态
    for (int i = 0; i < 1 << m; ++ i) {
        if (check(i)) {
            state.push_back(i);
            cnt.push_back(count(i));
        }
    }
    //处理前 i 行
    for (int i = 1; i <= n + 2; ++ i) {
        // 第 i - 2 行的状态
        for (int j = 0; j < state.size(); ++ j) {
            // 第 i - 1 行的状态
            for (int k = 0; k < state.size(); ++ k) {
                //第 i 行的状态
                for (int u = 0; u < state.size(); ++ u) {
                    int a = state[j], b = state[k], c = state[u];
                    // 垂直方向有两个1及以上:continue
                    if ((c & b) || (c & a) || (b & a)) continue;
                    // 方案和地图有矛盾:continue
                    if ((c & book[i]) || (b & book[i - 1])) continue;
                    // 因为 i 是奇偶交替,所以直接 & 1 可以有滚动数组的效果
                    dp[i & 1][k][u] = max(dp[i & 1][k][u], dp[i - 1 & 1][j][k] + cnt[u]);
                }
            }
        }
    }
    cout << dp[n + 2 & 1][0][0];  //需要加2,因为dp[n+1][0][0]中,第n行不一定要是state[0]
    return 0;
}

3、

三、区间DP

四、树形DP

五、数位DP

六、单调队列优化DP

七、斜率优化DP

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

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

相关文章

IDEA创建接口类和接口实现类

IDEA创建接口类和接口实现类 IDEA创建接口类IDEA创建接口实现类 以创建Dao包下的代码为例。 IDEA创建接口类 选中要创建接口类的package&#xff0c;右键菜单依次选择New——Java Class。 在弹出的界面中&#xff0c;将创建的对象类型由Class改为Interface&#xff0c;如下图…

Jmeter接口测试流程详解

1、jmeter简介 Jmeter是由Apache公司开发的java开源项目&#xff0c;所以想要使用它必须基于java环境才可以&#xff1b; Jmeter采用多线程&#xff0c;允许通过多个线程并发取样或通过独立的线程对不同的功能同时取样。 2、jmeter安装 首先需要安装jdk&#xff08;最好是最…

“锻造”微生物组以帮助我们长寿和繁荣

谷禾健康 衰老通常伴随着心血管、神经和免疫系统等一系列疾病的风险增加。 虽然在理解微生物组导致与衰老相关的个别疾病的细胞和分子机制方面取得了显著进展&#xff0c;我们在之前的文章也有这方面的阐述&#xff1a; 肠道微生物群与健康长寿 肠道微生物群的老化及其对宿主免…

二、Linux入门| shell运行原理及Linux权限的理解

一、Linux 软件包管理器 - yum centos7的安装方式 1、源码安装&#xff08;较复杂&#xff09; 2、rpm包安装&#xff08;较复杂&#xff0c;未解决依赖关系&#xff09; 3、yum安装&#xff08;不用编译源码&#xff0c;不用解决软件的依赖关系&#xff0c;门槛较低&#xff…

LeetCode4. 寻找两个正序数组的中位数

写在前面&#xff1a; 题目链接&#xff1a;LeetCode4. 寻找两个正序数组的中位数 编程语言&#xff1a;C 题目难度&#xff1a;困难 一、题目描述 给定两个大小分别为 m 和 n 的正序&#xff08;从小到大&#xff09;数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中…

英文论文润色哪家好用比较好,有值得推荐的吗

英文论文润色 推荐 英文论文润色对于写作者来说是一项十分重要的任务&#xff0c;它可以帮助我们修改文章中的语法、标点和排版等问题&#xff0c;使论文更加准确和易读。在众多的英文润色软件中&#xff0c;147chatgpt改写润色软件是一款值得推荐的全自动批量图文润色、自动纠…

SSM框架学习-核心容器小结

1. 容器相关 Spring核心容器中的容器是指容器对象&#xff0c;用于管理和装配Bean。它主要包含以下四个容器&#xff1a; BeanFactory容器&#xff1a;是最简单的容器&#xff0c;提供实例化、配置和管理对象的基本功能&#xff0c;但不提供AOP、事务管理等高级功能。 Applica…

三分钟,带你了解零代码开发

企业数字化转型如火如荼的进行&#xff0c;五花八门的零代码、低代码工具正如雨后春笋一般出现&#xff0c;那么零代码开发是什么&#xff1f; 阅读本文您将了解&#xff1a; 零代码开发是什么零代码与企业数字化转型零代码开发带来的效益简道云零代码平台应用实例 一、零代…

3ds Max云渲染有多快,3ds Max云渲染怎么用?

本地渲染效果图和动画3D项目是一个非常耗时的过程&#xff0c;当在场景中使用未优化的几何体或在最终渲染中使用大量多边形模型时&#xff0c;诸如此类的变量最终会增加渲染项目所需的时间和处理器能力。随着提供的渲染服务的云渲染平台出现&#xff0c;越来越多动画师、艺术家…

【ChirpStack 】如何获取 JWT TOKEN并利用 API 下发数据?

LoRa App Server 提供了两类 API 接口&#xff0c;其中 RESTful JSON API 提供了一个 API console&#xff0c;在AS地址的基础上使用 /api 即可访问&#xff0c;罗列了 API 端点和文档介绍&#xff0c;测试起来非常方便。 本文主要介绍 如何使用 chirpstack 的API 进行测试以及…

日常问题----如和解决跨域

一、什么是跨域 跨域不是问题&#xff0c;是一种安全机制。 同源策略是浏览器一个重要的安全策略&#xff0c;一个url由三部分组成:协议&#xff0c;域名&#xff08;ip地址&#xff09;&#xff0c;端口。所谓的同源就是指两个域有相同的协议&#xff08;protocol&#xff09…

7种常见的生产级负载均衡算法

准备测试数据 package com.example.demo.balance;import java.util.*;/*** author liwenchao*/ public class ServerIps {public static final List<String> LIST Arrays.asList("192.168.0.1","192.168.0.2","192.168.0.3","192.1…

聊聊那些年我们实现java AOP几种常见套路

前言 有一定开发经验的同学对AOP应该很了解吧&#xff0c;如果不了解&#xff0c;可以先查看如下文章进行科普一下https://baike.baidu.com/item/AOP/1332219?fraladdin&#xff0c;再来阅读本文。 示例前置准备 注&#xff1a; 本示例基于springboot进行演示 1、在项目pom…

将ABC文件 通过BlendShape导出为FBX>

将ABC文件 通过BlendShape导出为FBX 一、应用场景&#xff1a; 此项目为高中化学实验案例&#xff0c;为实现保鲜膜 模拟动画&#xff0c;这里通过使用MarvelousDesigner来结算出动画效果&#xff0c;导出ABC格式带动画后&#xff0c;导入到maya当中&#xff0c;这里因为需要…

SSM框架学习-注解开发定义bean

注解开发定义的bean和xml文件定义的bean有以下区别&#xff1a; 配置方式不同&#xff1a;注解方式是直接在Java类中使用注解来定义bean&#xff0c;而XML方式则是在XML文件中配置bean。 配置信息不同&#xff1a;注解方式在注解内配置bean的属性&#xff0c;如Value&#xff…

springboot整合ES

也可以直接看到最后&#xff0c;直接看到最后&#xff0c;中间都是废话废话废话&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;好气啊 1.刚下载完成,输入localhost:9200就报错&#xff0c;整个人都不太好了 [2023-05-10T14:35:59,002][WARN ][o.…

DC域控服务器与辅助DC域控服务器创建

DC域控服务器与辅助DC域控服务器创建 一、准备条件 在虚拟机上准备三台Windows Server 2008 R2 ,一台作为主域控&#xff0c;一台作为额外域控辅域控&#xff0c;一台作为客户端。 主域控 的IP地址为--192.168.1.190, 注意&#xff1a;(Windows Server 2003 需要 设置 DNS为127…

烽火HG680KA-Hi3798MV310-当贝纯净桌面-卡刷固件包

烽火HG680KA-Hi3798MV310-当贝纯净桌面-卡刷固件包-内有教程 特点&#xff1a; 1、适用于对应型号的电视盒子刷机&#xff1b; 2、开放原厂固件屏蔽的市场安装和u盘安装apk&#xff1b; 3、修改dns&#xff0c;三网通用&#xff1b; 4、大量精简内置的没用的软件&#xff…

pytorch搭建EfficientnetV2网络

文章目录 前言一、EfficientnetV2二、网络结构1.Fused_MBConv2.MBConv 三、整体代码总结 论文地址&#xff1a;https://arxiv.org/abs/2104.00298 官方代码&#xff1a;https://github.com/google/automl/tree/master/efficientnetv2 参考链接&#xff1a;https://blog.csdn.ne…

经典:DotNetBar Suite UI 7.9 for WPF Crack

创建专业的 WPF 应用程序 DotNetBar Suite for WPF 是超过 38 个本机 Windows Presentation Foundation 控件的工具箱&#xff0c;用于创建专业的 WPF 应用程序。 Office 2016 类样式添加到功能区、日程安排和其他控件... 我们痴迷于控制性能和像素级细节。我们很自豪地说&…