CF 1114D Flood Fill 区间dp

博客围绕方格序列问题展开,给定带颜色的方格序列,可从某格子将周围同色连通区域换色,求让序列同色的最少操作次数。得出区间最后会变成头部或尾部颜色的规律,使用dp数组记录区间内变成头/尾的最少操作次数,并给出递推式和代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

TP

给出一个方格序列, 每个方格有颜色, 现在可以从某个格子开始将周围同色的连通区域变换成另一个颜色, 问最少操作多少次能让序列同色.

可以得到一个规律: 一个区间最后总是会变成头部的颜色或者尾部的颜色. 那么我们dp数组可以记录区间内变成头/尾最少的操作次数.

dp[s][t][x]代表s到t区间,颜色为最左/右的最少操作次数.

递推式:

dp[s][t][0]=min(dp[s+1][t][0]+c[s]!=c[s+1],dp[s+1][t][1]+c[s]!=c[t])

dp[s][t][1]=min(dp[s][t-1][0]+c[s]!=c[t],dp[s][t-1][1]+c[t-1]!=c[t])

 代码:

#include<bits/stdc++.h>

using namespace std;

void debug_out() {
    cerr << '\n';
}

template<typename T, typename ...R>
void debug_out(const T &f, const R &...r) {
    cerr << f << " ";
    debug_out(r...);
}

#define debug(...) cerr << "[" << #__VA_ARGS__ << "]: ", debug_out(__VA_ARGS__);

typedef long long ll;

const int M = 5005;
const int inf = 1e9 + 5;
const int mod = 1e9 + 7;

int dp[M][M][2];
int c[M];
int n;

void init() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%d", &c[i]);
    }
}

void solve() {
    for (int len = 1; len <= n; len++) {
        for (int s = 0; s + len - 1 < n; ++s) {
            int t = s + len - 1;
            if (s == t) {
                dp[s][t][0] = dp[s][t][1] = 0;
                continue;
            }
            dp[s][t][0] = dp[s][t][1] = len - 1;
            dp[s][t][0] =
                    min(dp[s + 1][t][0] + (c[s] != c[s + 1]), dp[s + 1][t][1] + (c[s] != c[t]));
            dp[s][t][1] =
                    min(dp[s][t - 1][0] + (c[s] != c[t]), dp[s][t - 1][1] + (c[t - 1] != c[t]));
        }
    }
/*    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; ++j) {
            printf("[%d,%d]:%d %d", i, j, dp[i][j][0], dp[i][j][1]);
        }
        puts("");
    }*/

    printf("%d\n", min(dp[0][n - 1][0], dp[0][n - 1][1]));
}

int main() {
    init();

    solve();

    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值