P4170 [CQOI2007]涂色(区间dp)

3 篇文章 0 订阅

题目链接

题目大意很简单,就是求一个空串对其进行最小几次操作,可以变为目标串:
每次的操作定义为:连续一个区间都改变为同一字母
样例:RBGBR
1.RRRRR
2.RGGGR
3.RGBGR

从对区间的操作和,1-n一段的最小值,可以判断为区间dp

f[i][j] 表示将第i到第j个字符涂成目标子串的最小代价

思路详解

初始化

1.因为取得的是操作成目标子串的最小代价,所以一开始要将所有的点初始化为最大值
2.对于每个长度为1的区间 也就是 f[i][i] 自己图自己 代价就是1

循环枚举

根据区间dp的惯例,循环一般分为三层,
第一层枚举的是区间的长度
第二层枚举起点
第三层枚举中间点

探究状态转移方程

长度为1的区间已经在初始化的时候讨论过了
长度为2就分两类讨论

1.如果两个点一样,那么就是f[i][i+1]=f[i][i]
2. 不一样f[i][i+1]=f[i][i]+1
长度为3~n
就可以发现
如果 头尾两个是相同的,那么只需要在上一次的涂色中多往外涂出一个
f [ i ][ j ] = min( f [ i + 1 ] [ j ] , f [ i ] [ j- 1 ] )
如果不同,那么就可以通过一个k,把整个区间分开来,这个区间的代价就是,分开两边加起来的和
f [ i ] [ j ] = m i n ( f [ i ] [ j ] , f [ i ] [ k ] + f [ k + 1 ] [ j ] ) ;

代码

for(int l=1;l<n;l++) //枚举区间长度
	for(int i=1;i+l<=n;i++)//起点
	{
		int j=i+l;//计算出区间的末尾点在哪里
		if(s[i]==s[j])f[i][j]=min(f[i+1][j],f[i][j-1]);//第一种转移
		else
			for(int k=i;k<j;k++)
			f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]);//第二种分开来合并转移
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值