1. 程式人生 > 其它 >【LG P4170】塗色

【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])

總結一下就是:

\[\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 的部落格 - 洛谷部落格

本作品採用 知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議 進行許可。

限於本人水平,如果文章有表述不當之處,還請不吝賜教。