DP(区间专题四)

这篇博客探讨了一个关于字符串染色的问题,目标是用最少的涂色次数将木板涂成特定颜色序列RGBGR。通过区间动态规划或记忆化搜索的方法,设定状态dp[l][r]表示子串的最少涂色次数,并根据边界条件和不同情况的转移方程进行计算。文章强调了状态设计的巧妙之处,特别是当两端点颜色不同时,将问题分解为两个短区间处理。
摘要由CSDN通过智能技术生成

题意: 假设你有一条长度为5的木版,初始时没有涂过任何颜色。你希望把它的5个单位长度分别涂上红、绿、蓝、绿、红色,用一个长度为5的字符串表示这个目标:RGBGR。每次你可以把一段连续的木版涂成一个给定的颜色,后涂的颜色覆盖先涂的颜色。例如第一次把木版涂成RRRRR,第二次涂成RGGGR,第三次涂成RGBGR,达到目标。用尽量少的涂色次数达到目标。

>> face <<

Strategy: 区间dp or 记忆化搜索

题意是求对字符串的最少染色次数,设f[i][j]为字符串的子串s[i]~s[j]的最少染色次数,我们分析一下:当i==j时,子串明显只需要涂色一次,于是f[i][j]=1。当i!=j且s[i]==s[j]时,可以想到只需要在首次涂色时多涂一格即可,于是f[i][j]=min(f[i][j-1],f[i+1][j])当i!=j且s[i]!=s[j]时,我们需要考虑将子串断成两部分来涂色,于是需要枚举子串的断点,设断点为k,那么f[i][j]=min(f[i][j],f[i][k]+f[k+1][j])

状态: d p [ l ] [ r ] → dp[l][r]\to dp[l][r]该区间内的最少步数

目标: dp[1][n];

边界: dp[i][i] = a[i];

合法判断: d p [ l ] [ k ] = = d p [ k + 1 ] [ r ] dp[l][k] == dp[k+1][r] dp[l][k]==dp[k+1][r] 成立才能转移

转移方程: 区间dp, 枚举未知, 让所有能转移到该未知的状态来转移, 方程见上

attention: 本题的巧妙之处在状态的设计, 当两端点不同的时候能联想到, 分成两段

双倍经验:

@author: jasonleft 区间dp
#include <bits/stdc++.h>
#include <bits/extc++.h>
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define _rev(i, a, b) for (int i = (a); i >= (b); --i)
#define _for(i, a, b) for (int i = (a); i < (b); ++i)
#define _rof(i, a, b) for (int i = (a); i > (b); --i)
#define ll long long
#define db double
#define oo 0x3f3f3f3f
#define eps 0.00001
#define all(x) x.begin(), x.end()
#define met(a, 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值