#区间dp#CF1114D Flood Fill

题目

有一个长度为\(n\)的颜色序列,在游戏前选择一个固定的位置,
若当前轮该位置的颜色为\(x\),那么可以将所有颜色为\(x\)的连通块改为任意颜色,
问最少进行多少轮使得区间\([1,n]\)颜色完全相同


分析

先将所有颜色连通块缩成一点,这样变成相邻不同的颜色序列,
\(dp[i][j]\)表示初始位置在\([i,j]\)的最少轮数,
那么\(dp[i][j]=\min\{dp[i][j-1],dp[i+1][j]\}+1\)(颜色不同)
\(dp[i][j]=dp[i+1][j-1]+1\)(颜色相同,即将\([i+1,j-1]\)颜色相同后将整个区间改为一种颜色)


代码

#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
int n,a[5011],dp[5011][5011];
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline signed min(int a,int b){return a<b?a:b;}
signed main(){
	for (rr int T=iut(),X=-1;T;--T){
		rr int x=iut();
		if (x!=X) X=x,a[++n]=x;
	}
	for (rr int i=n-1;i;--i)
	for (rr int j=i+1;j<=n;++j)
	if (a[i]==a[j]) dp[i][j]=dp[i+1][j-1]+1;
	    else dp[i][j]=min(dp[i][j-1],dp[i+1][j])+1;
	return !printf("%d",dp[1][n]);
}
posted @ 2021-03-05 21:17  lemondinosaur  阅读(57)  评论(0编辑  收藏  举报