算法学习 区间dp 涂色PAINT

题目链接:
牛客网 涂色PAINT
在这里插入图片描述
在这里插入图片描述
这是一道区间dp题,题目有小错误,字符串的长度不是5,而是小于1005的长度。
定义:f[i][j] 为区间[i,j]需要涂色最少的次数
我们可以发现这样一件事:我们涂色尽量从最两端的颜色开始涂,虽然无从证明,但是对该题是正确的结论。
假设字符串为s,当区间[i,j]两端颜色相同时,可以先把整段区间涂成该种颜色,所以此时省略一步,即
f[i][j]=min(f[i+1][j],f[i][j-1]);
只有这种情况特殊,之后套用区间dp模板即可:

	for(int l = 1; l <= len; l++) {//枚举长度 
		for(int i = 1; i+l <= len;i++){//枚举起点
			int j = i+l;//枚举终点
			if(s[i] == s[j]) f[i][j] = min(f[i][j],min(f[i+1][j],f[i][j-1]));//若两段点相同,省一步
			else {//对f[i][k]、f[k+1][j](i<=k<j)区间进行枚举
				for(int k = i; k < j;k++){
					f[i][j] = min(f[i][k]+f[k+1][j],f[i][j]);
				} 
			}
		}
	}

要注意预处理,所有的区间先预处理为infinity
并且for i = 1 to len 都有f[i][i]=1

最终代码如下

#include <bits/stdc++.h>
#define LL long long
#define INF 50
#define MAXN 45
using namespace std;

int f[MAXN][MAXN]; 
char s[MAXN];

int main() {
	scanf("%s",s+1);
	int len = strlen(s+1);
	for(int i = 1; i <= len; i++) {
		for(int j = 1; j <= len;j++){
			f[i][j] = INF;
		}
	}
	for(int i = 1; i <= len; i++) {
		f[i][i] = 1;
	}
	for(int l = 1; l <= len; l++) {//枚举长度 
		for(int i = 1; i+l <= len;i++){//枚举起点
			int j = i+ l;//枚举终点 
			if(s[i] == s[j]) f[i][j] = min(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][k]+f[k+1][j],f[i][j]);
				} 
			}
		}
	}
	cout << f[1][len]; 
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值