蓝桥杯每日一题----区间dp

news2024/11/28 16:27:18

前言

暂时没啥好说的,直接进入正题吧

引入

涂色PAINT


读题发现要求的是使一段区间满足要求的最小操作次数,考虑用动态规划去做。
第一步:考虑缩小规模,这里的规模其实就是区间长度,那么dp数组应该可以表示某个区间,所以到这里dp数组至少是二维的,也就是dp[i][j],表示让区间[i,j]合法的最小操作次数。
第二步:考虑限制,这里暂时看不出来有啥限制,那就先不管。
第三步:根据写出来的dp数组推转移方程,dp[i][j]可以从三个地方转移dp[i-1][j],dp[i][j-1],dp[i-1][j-1],考虑这三个转移有什么特点,假设我现在已经求出了dp[i-1][j-1]的染色次数,那么当s[i]=s[j]时,我只需要在对dp[i-1][j-1]染色之前,把区间[i,j]进行一次涂色,涂成s[i]的颜色,这样再执行dp[i-1][j-1]得到的就是对区间[i,j]染成了要求的颜色,那么染色次数dp[i][j]=dp[i-1][j-1]+1;假设我现在已经求出了dp[i-1][j]的染色次数,那么当s[i]=s[j]时,我只需要在对第j个木板进行染色时同时捎带着把第i个木板染了就行,那么染色次数dp[i][j]=dp[i-1][j];假设我现在已经求出了dp[i][j-1]的染色次数,那么当s[i]=s[j]时,我只需要在对第i个木板进行染色时同时捎带着把第j个木板染了就行,那么染色次数dp[i][j]=dp[i][j-1];可以考虑三者取最小值。
综上,当s[i]=s[j]时,dp[i][j]=min(dp[i-1][j-1]+1,dp[i][j-1],dp[i-1][j])
那么当s[i]!=s[j]时,没有办法直接求这个大区间,那么就从小区间考虑,即断开区间。假设断点是k,分别求dp[i][k]和dp[k+1][j],再加起来即可,对于不同的断点取最小值。
第四步:考虑要写代码了,这里要注意一下dp数组如何初始化,我们可以明确的知道,区间长度为1时,所需要的操作次数就是1,所以初始化区间长度为1的值。我们要求的是最小值,其它位置上的值可以初始化为一个较大的值,也可以直接是0,但是在求解过程中要特判一下。
第五步:考虑区间dp的板子,区间dp一般三层for循环,第一层遍历区间长度,一般由2开始。
第二层遍历区间左端点,根据区间左端点和区间长度,区间右端点也就出来了。
第三层遍历区间断点。
这道题目就分析完了,还是给了两个版本的代码,一个是我初学时写的,一个是现在写的,都能AC,但是现在写的更规范一点

package java动态规划;

import java.util.Arrays;
import java.util.Scanner;

public class ok涂色 {
public static void main(String[] args) {
	Scanner scanner = new Scanner(System.in);
	char s[] = (" "+scanner.next()).toCharArray();
	int n = s.length-1;
	int dp[][] = new int[n+1][n+1];
	for(int i = 0;i <= n;i++) Arrays.fill(dp[i], Integer.MAX_VALUE/2);
	for(int i = 0;i <= n;i++) dp[i][i] = 1;
	for(int len = 2;len <= n;len++) {
		for(int l = 1;l+len-1<=n;l++) {
			int r = len+l-1;
			if(s[l]==s[r]) dp[l][r] = Math.min(dp[l+1][r], dp[l][r-1]);
			else {
				for(int k = l;k < r;k++)
					dp[l][r] = Math.min(dp[l][r], dp[l][k]+dp[k+1][r]);
			}
		}
	}
	System.out.println(dp[1][n]);
}
}
import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		String string = scanner.next();
		char[] s = string.toCharArray();
		int[][] dp = new int[string.length()][string.length()];
		// 初始化
		for (int i = 0; i < dp.length; i++) {
			dp[i][i] = 1;
		}

		for (int i = 1; i < string.length(); i++) {
			for (int j = 0; j + i < string.length(); j++) {
				int l = j;
				int r = j + i;
				if (s[l] == s[r]) {
					dp[l][r] = Math.min(dp[l + 1][r], dp[l][r - 1]);
				} else {
					for (int k = l; k < r; k++) {
						if (dp[l][r] != 0) {
							dp[l][r] = Math.min(dp[l][k] + dp[k + 1][r], dp[l][r]);
						} else {
							dp[l][r] = dp[l][k] + dp[k + 1][r];
						}
					}
				}
			}
		}
		System.out.println(dp[0][string.length() - 1]);
	}
}

例题2

合并回文子串

这道题稍微难一点,关键在于要想到用区间dp去做,并且明确区间是谁。我们要合并字符串A和B,那么可以考虑一点一点的合并,比如A的某个区间和B的某个区间进行合并。
第一步:考虑规模,这里的规模就是要合并的两个字符串,那么其实也就是有两个区间,字符串A的区间和字符串B的区间,那么dp数组就是四维的,dp[i][j][k][l]表示将字符串Ai-Aj与字符串Bk-Bl是否能形成回文串,如果可以那么回文串的长度就是(j-i+1)+(l-k+1).
第二步:考虑限制,限制就是不能更改原串字符的相对顺序,但是这里不知道怎么加在dp数组中,暂时一放。
第三步:推状态转移方程
对于dp[i][j][k][l],考虑一下如果怎么变成回文,i和j可以是对应的回文,j和k也可以是对应的回文,i和l可以是对应的回文,k和l可以是对应的回文。
那么考虑i和k可以是对应的回文吗?若可以,那么位置k必然是在l的右边,这样就打乱了数组B的原始顺序,所以是不可以的,其它非法方案也是类似。
若A[i]=A[j],则dp[i][j][k][l]可以从dp[i-1][j-1][k][l]转移过来,我只是想判断这种情况是否是回文,若是则为1,否则则为0,所以转移的时候可以直接用或运算转移,即dp[i][j][k][l]|=dp[i-1][j-1][k][l]。其他情况类似,于是有这样的转移方程,
若A[i]=A[j],则dp[i][j][k][l]|=dp[i+1][j-1][k][l]
若A[j]=A[k],则dp[i][j][k][l]|=dp[i][j][k+1][l-1]
若A[i]=A[l],则dp[i][j][k][l]|=dp[i+1][j][k][l-1]
若A[k]=A[j],则dp[i][j][k][l]|=dp[i][j+1][k-1][l]
当相等的情况不满足时,其实也就是无法构成回文,不必考虑。
第四步:考虑写代码,这里有两个区间,所以前两个for循环分别表示两个区间的长度,后两个for循环分别表示区间的左端点,因为这里没有断开区间操作,所以不用遍历断点。这里在写的时候注意是从区间长度为0开始遍历的,当总区间长度小于等于1时必然是回文,也就是len1+len2<=1时,直接是dp[i][j][k][l]=1。当然也可以预处理出来总长度为1的情况,但是不要漏处理了。

参考代码

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int t = scanner.nextInt();
        while (t > 0) {
            t--;
            String a = scanner.next();
            String b = scanner.next();
            int n1 = a.length();
            int n2 = b.length();
            int dp[][][][] = new int[n1 + 5][n1 + 5][n2 + 5][n2 + 5];
            a = " " + a + " ";
            b = " " + b + " ";
            int res = 0;
            for (int len1 = 0; len1 < n1 + 1 ; len1++) {
                for (int len2 = 0; len2 < n2 + 1; len2++) {
                    for (int l1 = 1, r1 = len1 + l1 - 1; r1 < n1 + 1; l1++, r1++) {
                        for (int l2 = 1, r2 = len2 + l2 - 1; r2 < n2 + 1; l2++, r2++) {
//                      int r1 = len1+l1-1;
//                      int r2 = len2+l2-1;
                            if (len1 + len2 <= 1) {
                                dp[l1][r1][l2][r2] = 1;
                            } else {
                                if (r2 > 0 && a.charAt(l1) == b.charAt(r2))
                                    dp[l1][r1][l2][r2] |= dp[l1 + 1][r1][l2][r2 - 1];
                                if (r1 > 0 && a.charAt(r1) == b.charAt(l2))
                                    dp[l1][r1][l2][r2] |= dp[l1][r1 - 1][l2 + 1][r2];
                                if (r1 > 0 && a.charAt(l1) == a.charAt(r1))
                                    dp[l1][r1][l2][r2] |= dp[l1 + 1][r1 - 1][l2][r2];
                                if (r2 > 0 && b.charAt(l2) == b.charAt(r2))
                                    dp[l1][r1][l2][r2] |= dp[l1][r1][l2 + 1][r2 - 1];

                                if (dp[l1][r1][l2][r2] == 1) {
                                    res = Math.max(res, len1 + len2);
                                }
                            }

                        }
                    }
                }
            }
            System.out.println(res);
        }
    }
}

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

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

相关文章

白话 Transformer 原理-以 BERT 模型为例

白话 Transformer 原理-以 BERT 模型为例 第一部分:引入 1-向量 在数字化时代,数学运算最小单位通常是自然数字,但在 AI 时代,这个最小单元变成了向量,这是数字化时代计算和智能化时代最重要的差别之一。 举个例子:银行在放款前,需要评估一个人的信用度;对于用户而…

解析Python中HTTP代理的常见问题

在Python编程中&#xff0c;HTTP代理是一个经常被提及的概念&#xff0c;尤其在处理网络请求和爬虫时。但与此同时&#xff0c;使用HTTP代理也经常会遇到一些令人头疼的问题。接下来&#xff0c;就让我们一起解析一下Python中使用HTTP代理时常见的那些问题。 1. 代理服务器无响…

06、全文检索 -- Solr -- Solr 全文检索之在图形界面管理 Core 的 Schema(演示对 普通字段、动态字段、拷贝字段 的添加和删除)

目录 Solr 全文检索之管理 Schema使用Web控制台管理Core的Schema3 种 字段解释&#xff1a;Field&#xff1a;普通字段Dynamic Field&#xff1a;动态字段Copy Field&#xff1a;拷贝字段 演示&#xff1a;添加 普通字段&#xff08; Field &#xff09;演示&#xff1a;添加 动…

CSS写渐变边框线条

box-sizing: border-box; border-top: 1px solid; border-image: linear-gradient(to right, red, blue) 1;

建筑行业数字化:从设计到运维的全面革新

随着科技的快速发展&#xff0c;数字化技术在各行各业中的应用越来越广泛。建筑行业作为传统产业&#xff0c;也在积极拥抱数字化技术&#xff0c;以提高效率、降低成本并实现可持续发展。本文将主要探讨建筑行业数字化的几个关键领域&#xff0c;包括建筑设计数字化、施工管理…

CDH6.3.2 多 Spark 版本共存

一 部署Spark客户端 1.1 部署spark3客户端 tar -zxvf spark-3.3.1-bin-3.0.0-cdh6.3.2.tgz -C /opt/cloudera/parcels/CDH/lib cd /opt/cloudera/parcels/CDH/lib mv spark-3.3.1-bin-3.0.0-cdh6.3.2/ spark3将 CDH 集群的 spark-env.sh 复制到 /opt/cloudera/parcels/CDH/li…

《Python 网络爬虫简易速速上手小册》第3章:Python 网络爬虫的设计(2024 最新版)

文章目录 3.1 设计高效的爬取策略3.1.1 重点基础知识讲解3.1.2 重点案例&#xff1a;使用 Scrapy 框架进行并发爬取3.1.3 拓展案例 1&#xff1a;使用 Requests 和 gevent 进行异步请求3.1.4 拓展案例 2&#xff1a;利用缓存机制避免重复请求 3.2 管理爬虫的请求频率3.2.1 重点…

【AIGC核心技术剖析】AI生成音乐:MAGNeT一种直接操作多个音频令牌流的掩码生成序列建模方法

MAGNeT是一种直接操作多个音频令牌流的掩码生成序列建模方法。与先前的工作不同&#xff0c;MAGNeT由一个单阶段、非自回归的变压器组成。在训练期间&#xff0c;论文使用掩码调度器预测从掩码令牌中获得的跨度&#xff0c;而在推断期间&#xff0c;论文通过多个解码步骤逐渐构…

微信小程序 使用npm包

1. 微信小程序 使用npm包 1.1. npm初始化 如果你的小程序项目没有安装过npm包的话&#xff0c;你需要先初始化npm npm init1.2. 安装npm包 这里以vant-weapp(小程序UI组件库)为例&#xff1a; npm i vant-weapp -S --production1.3. npm包构建 1.3.1. 点击微信开发者工具右…

怎样理解Vue单向数据流

在前端开发中&#xff0c;数据流是一个非常重要的概念。Vue.js作为一种流行的前端框架&#xff0c;采用了单向数据流的架构&#xff0c;旨在简化开发过程并提高应用的可维护性。本文将探讨Vue单向数据流的含义以及它的使用方法。 什么是单向数据流&#xff1f; 在Vue中&#…

靶机实战bwapp亲测xxe漏洞攻击及自动化XXE注射工具分析利用

靶机实战bwapp亲测xxe漏洞攻击及自动化XXE注射工具分析利用。 1|0介绍 xxe漏洞主要针对webservice危险的引用的外部实体并且未对外部实体进行敏感字符的过滤,从而可以造成命令执行,目录遍历等.首先存在漏洞的web服务一定是存在xml传输数据的,可以在http头的content-type中查…

动态颗粒背景,适合VUE、HTML前端显示

动态颗粒背景&#xff0c;适合做背景使用&#xff0c;VUE、HTML前端显示直接看效果 废话不多说直接上代码&#xff1b; 一、html 代码部分 <template><div id"login"><div class"container"><div class"login-form"&g…

golang开发window环境搭建

1.本人开发环境&#xff1a;window10,idea2020.1.3 2.Go语言环境版本1.5.1 2.1. go语言插件 下载地址 csdn - 安全中心 2.2下载安装 3.idea配置go环境 4.创建go项目 、5.运行

第二届 N1CTF Junior WEB方向 部分题解WP

zako 题目描述&#xff1a;很简单的rce哦 启动环境&#xff0c;源码直接给了。 execute.sh #!/bin/bashreject(){echo ${1}exit 1 }XXXCMD$1awk -v str"${XXXCMD}" \ BEGIN{deny";&$(){}[]!#$%^&*-";for(i 1; i < length(str); i){char su…

Unity引擎学习笔记之【混合动画操作】

混合动画Hybrid Animation Unity中的Blend Tree是一种动画混合技术&#xff0c;它允许开发者通过添加多个动画片段&#xff08;例如奔跑、行走、跳跃等&#xff09;来创建复杂的角色动画。Blend Tree允许在不同的状态下平滑地过渡并混合不同的动画。例如&#xff0c;在奔跑和行…

PyTorch 2.2 中文官方教程(九)

在生产环境中部署 PyTorch 模型 通过 Flask 在 Python 中部署 PyTorch 的 REST API 原文&#xff1a;pytorch.org/tutorials/intermediate/flask_rest_api_tutorial.html 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 注意 点击这里下载完整的示例代码 作者&#…

1997-2022年中央对各省份一般公共预算转移支付数据

1997-2022年中央对各省份一般公共预算转移支付数据 1、时间&#xff1a;1997-2022年 2、范围&#xff1a;31省 3、指标&#xff1a;一般公共预算转移支付 4、来源&#xff1a;wind 财政部 5、指标解释&#xff1a;一般性转移支付又称体制性转移支付&#xff0c;是指上级政…

机器学习本科课程 实验3 决策树处理分类任务

实验3.1 决策树处理分类任务 使用sklearn.tree.DecisionTreeClassifier完成肿瘤分类&#xff08;breast-cancer&#xff09;计算最大深度为10时&#xff0c;十折交叉验证的精度(accuracy)&#xff0c;查准率(precision)&#xff0c;查全率(recall)&#xff0c;F1值绘制最大深度…

前端学习第4天

一、复合选择器 1.后代选择器 2.子代选择器 3.并集选择器 4.交集选择器 5.伪类选择器 1.伪类-超链接&#xff08;拓展&#xff09; 二、CSS特性 1.继承性 body放在style中 2.层叠性 3.优先级 属性 !important;&#xff08;最高优先级&#xff09; 1.优先级-叠加计算规则 2.em…

枚举(Java)

一、概念 枚举是一种特殊的类。 格式&#xff1a; 修饰符 enum 枚举类名{ 对象名称1&#xff0c;对象名称2&#xff0c;....; 其他成员... } 二、枚举类的特点 1.枚举类的第一行只能罗列一些名称&#xff0c;并且这些名称都是常量&#xff0c;每个常量记住一个枚举类对象…