【LG P4170】涂色

解析

题意是求对字符串的最少染色次数,设 f[i][j] 为字符串的子串 s[i] ~ s[j] 的最少染色次数,我们分析一下:

i==j 时,子串明显只需要涂色一次,于是 f[i][j]=1

i!=js[i]==s[j] 时,可以想到只需要在首次涂色时多涂一格即可,于是 f[i][j]=min(f[i][j-1],f[i+1][j])

i!=js[i]!=s[j] 时,我们需要考虑将子串断成两部分来涂色,于是需要枚举子串的断点,设断点为 k,那么 f[i][j]=min(f[i][j],f[i][k]+f[k+1][j])

总结一下就是:

\[\large\begin{equation} f_{i,j}= \begin{cases} 1 & i=j\\ \min(f_{i,j-1},f_{i+1,j}) & i\not=j,s_i=s_j\\ \min(f_{i,j},f_{i,k}+f_{k+1,j}) & i\not=j,s_i\not=s_j \end{cases} \end{equation} \]

由于 f[i][j] 的定义,我们可以知道 f[1][n] 即为答案。

代码

#include<bits/stdc++.h>
using namespace std;
char c[55];
int f[55][55];
int main() {
	scanf("%s",c+1);
	int n=strlen(c+1);
	memset(f,0x7F,sizeof(f));
	for(int i=1; i<=n; i++) {
		f[i][i]=1;
	}
	for(int i=2; i<=n; i++) {
		for(int l=1; l<=n; l++) {
			int r=l+i-1;
			if(r>n) {
				break;
			}
			if(c[l]==c[r]) {
				f[l][r]=min(f[l+1][r],f[l][r-1]);
			} else {
				for(int k=l; k<r; k++) {
					f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]);
				}
			}
		}
	}
	printf("%d",f[1][n]);
	return 0;
}

参考资料

P4170 涂色 - Loner_Knowledge 的博客 - 洛谷博客

上一篇:LeetCode-55. 跳跃游戏


下一篇:数据可视化基础专题(55):Pandas基础(19)常用函数(四)绘图与元素级运算函数