【题解】颜色联通块

题目

题目描述

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

输入格式

输入的第一行包含一个正整数 N N ,( 1 < = N < = 5000 1 <= N <= 5000 )代表方块的个数。

输入的第二行包含 N N 个正整数,分别代表每一个方块的颜色。

输出格式

输出最少的步数。

样例

样例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

样例1解释

[5 2 2 1] -> [5 5 5 1] -> [1 1 1 1] 

题解

定义dp[i][j]表示将 [ i , j ] [i,j] 变为连通块的最少步骤数

为了方便计算,我们不妨把已经联通的块缩成一个点,这样不会影响答案

现在考虑dp[i][j]如何得出:

a[i]==a[j],即两边颜色一样

那么把 [ i + 1 , j 1 ] [i+1,j-1] 变为两边的颜色即可,即是dp[i+1][j-1]+1

a[i]!=a[j],即两边颜色不一样

我们可以使 [ i , j 1 ] [i,j-1] 变为跟 j j 一样的颜色即可
同理可以使 [ i + 1 , j ] [i+1,j] 变为跟 i i 一样的颜色
两种方法中取最优的

即是min(dp[l][r-1],dp[l+1][r])+1

代码

缩点

n=unique(s+1,s+1+n)-s-1;

区间DP

for(int len=1;len<=n;len++){
	for(int l=1;l<=n-len+1;l++){
		int r=l+len-1;
		if(s[l]==s[r]){
			dp[l][r]=dp[l+1][r-1]+1;
		} 
		else{
			dp[l][r]=min(dp[l][r-1],dp[l+1][r])+1;
		}
	}
}

完整代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<bits/stdc++.h>
using namespace std;
const int MAXN=5005;
int n;
int s[MAXN];
int dp[MAXN][MAXN];
int main(){
//	freopen("flood.in","r",stdin);
//	freopen("flood.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&s[i]);
	}
	for(int i=1;i<=n;i++){
		dp[i][i]=1;
	}
	n=unique(s+1,s+1+n)-s-1;
	for(int len=1;len<=n;len++){
		for(int l=1;l<=n-len+1;l++){
			int r=l+len-1;
			if(s[l]==s[r]){
				dp[l][r]=dp[l+1][r-1]+1;
			} 
			else{
				dp[l][r]=min(dp[l][r-1],dp[l+1][r])+1;
			}
		}
	}
	printf("%d",dp[1][n]-1);
return 0;
} 

猜你喜欢

转载自blog.csdn.net/tanfuwen_/article/details/107451346
今日推荐