#区间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]);
}