CF1114D Flood Fill

CF1114D Flood Fill

题目

题目描述

You are given a line of nn colored squares in a row, numbered from 11 to n n n from left to right. The i i i -th square initially has the color c i c_i ci .Let’s say, that two squares i i i and j j j belong to the same connected component if c i = c j ​ c_i = c_j​ ci=cj , and c i = c k c_i = c_k ci=ck​ for all k k k satisfying i < k < j i < k < j i<k<j . In other words, all squares on the segment from i i i to j j j should have the same color.For example, the line [ 3 , 3 , 3 ] [3, 3, 3] [3,3,3] has 11 connected component, while the line [ 5 , 2 , 4 , 4 ] [5, 2, 4, 4] [5,2,4,4] has 3 3 3 connected components.The game “flood fill” is played on the given line as follows:At the start of the game you pick any starting square (this is not counted as a turn).Then, in each game turn, change the color of the connected component containing the starting square to any other color.Find the minimum number of turns needed for the entire line to be changed into a single color.

输入格式

The first line contains a single integer n n n ( 1 ≤ n ≤ 5000 1\le n \le5000 1n5000 ) — the number of squares.The second line contains integers c 1 , c 2 , … , c n c_1, c_2, \ldots, c_n c1,c2,,cn​ ( 1 ≤ c i ≤ 5000 1 \le c_i \le 5000 1ci5000 ) — the initial colors of the squares.

输出格式

Print a single integer — the minimum number of the turns needed.

题意翻译

n 个方块排成一排,第 i i i 个颜色为 c i c_i ci​。定义一个颜色联通块 [ l , r ] [l,r] [l,r] 当且仅当 l l l r r r 之间(包括 l , r l,r l,r)所有方块的颜色相同。现在你可以选定一个起始位置 p p p,每次将 p p p 所在颜色联通块的所有方块颜色改成另一种。这个操作可能将多个颜色联通块合并成一个。问最少要多少步,能让 [ 1 , n ] [1,n] [1,n]变成一个颜色联通块

数据范围

1 ≤ n , c i ​ ≤ 5000 。 1≤n,ci​≤5000。 1n,ci5000

输入输出样例
输入 #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
说明/提示

In the first example, a possible way to achieve an optimal answer is to pick square with index 2 2 2 as the starting square and then play as follows:

  • [ 5 , 2 , 2 , 1 ] [5, 2, 2, 1] [5,2,2,1]
  • [ 5 , 5 , 5 , 1 ] [5, 5, 5, 1] [5,5,5,1]
  • [ 1 , 1 , 1 , 1 ] [1, 1, 1, 1] [1,1,1,1]

In the second example, a possible way to achieve an optimal answer is to pick square with index 5 5 5 as the starting square and then perform recoloring into colors 2 , 3 , 5 , 4 2, 3, 5, 4 2,3,5,4 in that order.In the third example, the line already consists of one color only.

原题链接

题解

思路

这道题是说的选定一个位置, 接着不停地改变这个位置所在颜色联通块的颜色, 直到所有位置颜色都相同。这里注意选定的位置不能改变, 只能在同一个地方进行改变颜色的操作。这道题的算法比较好分析, 可以进行区间合并, 那肯定就是区间dp了, 但是看到数据范围, n n n最大是5000, 一般的区间dp都是
O ( n 3 ) O(n^3) O(n3), 这是肯定会超时的, 所以我们应该想办法省掉一层循环。最外层循环是枚举的区间长度, 也就是区间dp的阶段, 第二层循环是枚举的起始位置,这两个很明显都不能去掉, 看来看去能够省下来的只能是最后枚举划分位置的那一层循环了。 接下来我们就要想如何省了。 我们通过读题, 知道了进行改变颜色的位置只能是在同一处, 所以我们枚举的每个两边不相等区间都可以由通过改变其中长度少1的区间变为剩下的那一个位置而得到, 既是
d p [ l ] [ r ] = m i n ( d p [ l + 1 ] [ r ] + 1 , d p [ l ] [ r − 1 ] + 1 ) dp[l][r] = min (dp[l + 1][r] + 1, dp[l][r - 1] + 1) dp[l][r]=min(dp[l+1][r]+1,dp[l][r1]+1)
而当两头一样的话就只需要改变内部, 使这个区间除去两端的区间颜色改变成两端一样的区间, 既是
d p [ l ] [ r ] = d p [ l + 1 ] [ r − 1 ] + 1 dp[l][r] = dp[l + 1][r - 1] + 1 dp[l][r]=dp[l+1][r1]+1
不过此时又有问题了, 如果里面还是一个两头相等且和外面一样的区间, 这样就不能加1了, 比如 2 , 2 , 2 , 2 2, 2, 2, 2 2,2,2,2这里一次都不需要改, 可是直接执行上面的方法就会输出 2 2 2, 这时候就需要在输入时就把所有颜色联通块的长度压缩成1。
方法:

for (int i = 1; i <= n; i++){
 scanf ("%d", &s[i]);
 if (s[i] == s[i - 1]){
  i --;
  n --;
 }
}

这样就可以避免上述情况发生

运用算法
区 间 d p 区间dp dp

代码

#include <cstdio>
#include <algorithm>
using namespace std;

#define MAXN 5000

int s[MAXN + 5], dp[MAXN + 5][MAXN + 5];

int main(){
	
	int n;
	
	scanf ("%d", &n);
	for (int i = 1; i <= n; i++){
		scanf ("%d", &s[i]);
		if (s[i] == s[i - 1]){//压缩联通块 
			i --;
			n --;
		}
	}
	//dp[i][i]就是0, 所以不用初始化 
	for (int i = 2; i <= n; i++){//枚举长度 
		for (int l = 1; l <= n - i + 1; l++){
			int r = l + i - 1;
			
			if (s[l] == s[r]){//如果两端相等, 就直接等于去除两端的区间加1 
				dp[l][r] = dp[l + 1][r - 1] + 1;
			}
			else {//否则比较从哪个变过来小 
				dp[l][r] = min (dp[l + 1][r], dp[l][r - 1]) + 1; 
			}
		}
	}
	
	printf ("%d", dp[1][n]);//输出整个区间的变化次数 
	
	return 0;
} 
  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值