【Codeforces Round #538 (Div. 2) D. Flood Fill】区间DP


D. Flood Fill

题意

给你一个颜色序列,每个位置有一个颜色,选择一个起始位置,每次可以改变包含这个位置的颜色段,将这个颜色段修改为任意一个颜色, 问最少操作多少次。

1 ≤ n ≤ 5000 1 \leq n \leq 5000 1n5000
做法

由于要求每次操作都要包含起始段,所以每次操作都应该是连续的,也就是如果我们现在改变 ( l , r ) , 那 么 ( l , r − 1 ) , ( l + 1 , r ) , ( l + 1 , r − 1 ) (l,r),那么(l,r-1),(l+1,r),(l+1,r-1) (l,r)(l,r1),(l+1,r),(l+1,r1)一定已经改变完成,所以直接 d p dp dp即可, d p [ l ] [ r ] dp[l][r] dp[l][r]表示将l-r这个区间变为同一种颜色的最小代价。
当l的颜色与r的颜色相同: 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
当l的颜色与r的颜色不同: d p [ l ] [ r ] = m i n ( d p [ l + 1 ] [ r ] , d p [ l ] [ r − 1 ] ) + 1 dp[l][r]=min(dp[l+1][r],dp[l][r-1])+1 dp[l][r]=min(dp[l+1][r],dp[l][r1])+1

代码

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
const int maxn = 5005;
const int INF = 0x3f3f3f3f;
int dp[maxn][maxn];
int a[maxn];
int b[maxn];
int dfs(int l,int r)
{
    if(dp[l][r]!=INF) return dp[l][r];
    if(l==r) dp[l][r]=0;
    else if(l+1==r) dp[l][r]=1;
    else if(b[l]==b[r]) dp[l][r]=dfs(l+1,r-1)+1;
    else dp[l][r]=min(dfs(l,r-1),dfs(l+1,r))+1;
    return dp[l][r];
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    memset(dp,INF,sizeof(dp));
    int cnt=0;
    for(int i=1;i<=n;i++) if(a[i]!=a[i-1]) b[++cnt]=a[i];
    printf("%d\n",dfs(1,cnt));
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值