当前位置: 首页 > news >正文

【蓝桥杯集训·每日一题】 AcWing 3996. 涂色

文章目录

  • 一、题目
    • 1、原题链接
    • 2、题目描述
  • 二、解题报告
    • 1、思路分析
    • 2、时间复杂度
    • 3、代码详解
  • 三、知识风暴
  • 区间DP
  • Unique函数

一、题目

1、原题链接

3996. 涂色

2、题目描述

有 n 个砖块排成一排,从左到右编号为 1∼n。

其中,第 i 个砖块的初始颜色为 ci。

我们规定,如果编号范围 [i,j] 内的所有砖块的颜色都相同,且当第 i−1 和 第 j+1 个砖块存在时,这两个砖块的颜色和区间 [i,j] 的颜色均不同, 则砖块 i 和 j 属于同一个连通块。

例如,[3,3,3] 有 1 个连通块,[5,2,4,4] 有 3 个连通块。

现在,要对砖块进行涂色操作。

开始所有操作之前,你需要任选一个砖块作为起始砖块

每次操作:

  1. 任选一种颜色。
  2. 将最开始选定的起始砖块所在连通块中包含的所有砖块都涂为选定颜色,

请问,至少需要多少次操作,才能使所有砖块都具有同一种颜色

输入格式

第一行包含整数 n。

第二行包含 n 个整数 c1,c2,…,cn。

输出格式

一个整数,表示所需要的最少操作次数。

数据范围

前六个测试点满足,1≤n≤20
所有测试点满足,1≤n≤5000,1≤ci≤5000

输入样例1

4
5 2 2 1

输出样例1

2

输入样例2

8
4 5 2 2 1 3 5 5

输出样例2

4

输入样例3

1
4

输出样例3

0

输入样例4

5
1 3 1 2 1

输出样例4

3

样例4解释

注意,每次染色操作所涉及的连通块必须包含所有操作开始前选定的起始砖块。

因此,答案是 3,而不是 2。

二、解题报告

1、思路分析

思路来源:y总讲解视频
y总yyds

(1)因为每次都是改变起始点所在的连通块,所以颜色相同的砖块一定是一起改变的,所以我们可以先将原序列中颜色相同的砖块简化成一个砖块。
(2)

  • dp[i][j]表示所有在[i,j]中选择起点,并且将[i,j]的所有砖块染成同一种颜色的所有方案数中的最小操作次数。

  • 根据第i个砖块和第j个砖块颜色是否相同进行划分:

    ①第i个砖块和第j个砖块颜色不同:

    • 最后染色的为i:即先求出[i+1,j]染成相同颜色的最小操作次数即dp[i+1][j],再加一次即将i染成与[i+1,j]相同的颜色,最小操作次数即为dp[i+1][j]+1
    • 最后染色的砖块为j:同理,最小操作次数为dp[i][j-1]+1

    ②第i个砖块和第j个砖块颜色相同:

    • 先将[i,j-2]染成相同颜色,再将j-1[i,j-2]染成相同颜色,最后将j[i,j-1]染成相同颜色:由于该方案是在dp[i][j-1]中的某些方案,也就是其子集,所以将[i,j-1]染成相同颜色的操作数是大于等于dp[i][j-1]。即总操作次数大于等于dp[i][j-1]+1
    • 先将[i+1,j-1]染成相同颜色,再将i[i+1,j-1]染成相同颜色,最后将j[i,j-1]染成相同颜色(即ij最后染色):即总操作次数为dp[i+1][j-1]+1
    • 由于第二种情况操作的区间比第一种情况操作的区间要短,所以可知,上述两种情况的最小操作次数为dp[i+1][j-1]+1
  • 综合上面三种情况,即第i个砖块和第j个砖块颜色不同时dp[i][j]=min(dp[i+1][j]+1,dp[i][j-1]+1,否则第i个砖块和第j个砖块颜色相同时,dp[i][j]=dp[i+1][j-1]+1

(3)利用上述思路,输出dp[1][n]即为答案。

2、时间复杂度

时间复杂度为O(n2)

3、代码详解

#include <iostream>
#include <algorithm>
using namespace std;
const int N=5010;
int c[N],dp[N][N];
int n;
int main(){cin>>n;for(int i=1;i<=n;i++) cin>>c[i];n=unique(c+1,c+n+1)-(c+1);    //对数组去重,即合并颜色相同的砖块//枚举所有可能的区间长度for(int len=2;len<=n;len++){for(int i=1;i+len-1<=n;i++){int j=i+len-1;//i和j颜色不同时的转移方程if(c[i]!=c[j]) dp[i][j]=min(dp[i][j-1],dp[i+1][j])+1;//i和j颜色相同时的转移方程else dp[i][j]=dp[i+1][j-1]+1;}}cout<<dp[1][n];return 0;
}

三、知识风暴

区间DP

Unique函数

  • 在头文件#include <algorithm>中包含。
  • 作用:对数组的相邻重复元素去重,并返回去重之后数组的尾地址(一般用unique的返回值减去数组的首地址来求去重后数组的元素个数),如果重复元素不相邻的话一般要先对原数组进行排序操作。
http://www.lryc.cn/news/45436.html

相关文章:

  • 人工智能中的Web端编程
  • jsp+mysql+J2EE校园自行车租赁系统cdA1A2程序
  • 当营养遇上肠道菌群:探究其对儿童健康的影响
  • vue尚品汇商城项目-day01【4.完成非路由组件Header与Footer业务】
  • IDEA安装教程(图文详解,一步搞定)
  • 【01 DualCam Porting】
  • redis --- string类型的使用
  • 康耐视visionpro-机器视觉定位引导-经验总结-来自视觉人粉丝分享
  • 包管理工具npm
  • ChatGPT正进军各行各业,抓住机遇,拥有无限的可能性。
  • Maven 多模块管理
  • crash 内核调试工具 ps 指令 显示的进程状态 RU, IN, UN, ZO, ST, TR, DE, SW, WA, PA 什么意思
  • Spring《二》bean的实例化与生命周期
  • java与kotlin 写法区别
  • 服务器运行深度学习代码使用指南
  • 计算机组成原理 - 2. 数据的表示和运算
  • 【js】基础知识点--语句,break和continue,switch,with,for..in,do-while,while
  • 【C++】迭代器
  • 数据可视化在前端中的应用
  • FFmpeg 合并视频文件没声音,不同步原因
  • 绕不开的“定位”
  • 《Effective Objective-C 2.0 》 阅读笔记 item12
  • 云原生计算能消除技术债务吗?
  • 9. 回文数
  • [SV]SystemVerilog线程之fork...join专题
  • 你看这个spring的aop它又大又宽
  • 设计模式-创建-单例模式
  • 使用mybatis-plus-generator配置一套适合你的CRUD
  • MATLAB实现各种离散概率密度函数(概率密度/分布/逆概率分布函数)
  • 指针的基本知识