[CQOI2007]塗色paint(BZOJ 1260)題解

題目描述

假設你有一條長度爲5的木版,初始時沒有塗過任何顏色。你但願把它的5個單位長度分別塗上紅、綠、藍、綠、紅色,用一個長度爲5的字符串表示這個目標:RGBGR。html

每次你能夠把一段連續的木版塗成一個給定的顏色,後塗的顏色覆蓋先塗的顏色。例如第一次把木版塗成RRRRR,第二次塗成RGGGR,第三次塗成RGBGR,達到目標。spa

用盡可能少的塗色次數達到目標。code

輸入輸出格式

輸入格式:htm

輸入僅一行,包含一個長度爲n的字符串,即塗色目標。字符串中的每一個字符都是一個大寫字母,不一樣的字母表明不一樣顏色,相同的字母表明相同顏色。blog

輸出格式:字符串

僅一行,包含一個數,即最少的塗色次數。string


很是明顯的一道區間DPit

關於區間DP轉https://www.cnblogs.com/lizitong/p/10014809.htmlio

咱們要將一個區間塗成給出的顏色。class

這道題的難點在於其與咱們的思惟相逆。

咱們主觀上的塗色所有都是先塗底層,而後在逐漸在上面覆蓋,而這道題的狀態轉移方程卻不一樣。

首先狀態,dp[i][j]表示[i]到[j]的最少次數。

注意清初值,因爲是求最小,初值清成正無窮,每一個單獨的顏色都須要塗,因此清成1。

當咱們枚舉長度的時候,若是[i][j]顏色相同,豈不是我在塗[i][j-1]或者[i+1][j]順帶一筆就能夠帶過去?

這就是我所說的與咱們印象相逆的地方。假設咱們現實中一筆帶過去,中間的顏色所有會變色,可是咱們這裏是一個逆向的過程,中間的顏色是創建在已經塗過的顏色基礎上的。

仔細想一想。

那若是[i][j]顏色不同呢?

那咱們就須要把這段區間分紅兩段塗,枚舉k在區間[i][j]中,把區間分紅兩段,而後將次數相加。

上代碼。歡迎你們在評論區留言討論。

#include<cstdio> #include<algorithm> #include<cstring> #include<string>
using namespace std; char c[55]; int dp[55][55]; int main() { scanf("%s",c+1); int l = strlen(c+1); memset(dp,0x3f,sizeof(dp)); for(int i = 1;i<=l;i++) { dp[i][i] = 1; } for(int len = 2;len<=l;len++) { for(int i = 1;i+len-1<=l;i++) { int j = i+len-1; if(c[i]==c[j]) { dp[i][j] = min(dp[i+1][j],dp[i][j-1]); }else { for(int k = i;k<j;k++) { dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j]); } } } } printf("%d",dp[1][l]); return 0; }
相關文章
相關標籤/搜索