假設你有一條長度為5的木版,初始時沒有塗過任何顏色。你希望把它的5個單位長度分別塗上紅、綠、藍、綠、紅色,用乙個長度為5的字串表示這個目標:rgbgr。
每次你可以把一段連續的木版塗成乙個給定的顏色,後塗的顏色覆蓋先塗的顏色。例如第一次把木版塗成rrrrr,第二次塗成rgggr,第三次塗成rgbgr,達到目標。
用盡量少的塗色次數達到目標。
輸入格式:
輸入僅一行,包含乙個長度為n的字串,即塗色目標。字串中的每個字元都是乙個大寫字母,不同的字母代表不同顏色,相同的字母代表相同顏色。
輸出格式:
僅一行,包含乙個數,即最少的塗色次數。
輸入樣例#1:
aaaaa
輸出樣例#1:
1
輸入樣例#2:
rgbgr
輸出樣例#2:
3
40%的資料滿足:1<=n<=10
100%的資料滿足:1<=n<=50
當i==j
時,子串明顯只需要塗色一次,於是f[i][j]=1
。
當i!=j
且s[i]==s[j]
時,可以想到只需要在首次塗色時多塗一格即可,於是f[i][j]=min(f[i][j-1],f[i+1][j])
當i!=j
且s[i]!=s[j]
時,我們需要考慮將子串斷成兩部分來塗色,於是需要列舉子串的斷點,設斷點為k
,那麼f[i][j]=min(f[i][j],f[i][k]+f[k+1][j])
總結一下就是:
f_=1\ (i==j)fi
,j=
1(i=
=j)f_=\min(f_,f_)\ (i!=j,\ s_i==s_j)fi
,j=
min(fi
,j−1
,fi
+1,j
)(i
!=j,
si=
=sj
)f_=\min(f_,f_+f_)\ (i!=j,\ s_i!=s_j,\ i\le kfi
,j=
min(fi
,j,
fi,k
+fk
+1,j
)(i
!=j,
si!
=sj
,i≤k
由於f[i][j]
的定義,我們可以知道f[1][n]
即為答案。
附**:
#include#include#include#include#define maxn 60
using namespace std;
int n,dp[maxn][maxn];
char s[maxn];
inline int read()
while(c>='0'&&c<='9')
return date*w;
}int main()
printf("%d\n",dp[1][n]);
return 0;
}
洛谷 P4170 CQOI2007 塗色
假設你有一條長度為5的木版,初始時沒有塗過任何顏色。你希望把它的5個單位長度分別塗上紅 綠 藍 綠 紅色,用乙個長度為5的字串表示這個目標 rgbgr。每次你可以把一段連續的木版塗成乙個給定的顏色,後塗的顏色覆蓋先塗的顏色。例如第一次把木版塗成rrrrr,第二次塗成rgggr,第三次塗成rgbgr,...
洛谷 P4170 CQOI2007 塗色
假設你有一條長度為5的木版,初始時沒有塗過任何顏色。你希望把它的5個單位長度分別塗上紅 綠 藍 綠 紅色,用乙個長度為5的字串表示這個目標 rgbgr。每次你可以把一段連續的木版塗成乙個給定的顏色,後塗的顏色覆蓋先塗的顏色。例如第一次把木版塗成rrrrr,第二次塗成rgggr,第三次塗成rgbgr,...
P4170 CQOI2007 塗色 題解
同步 原題鏈結 簡要題意 一開始你有乙個長度為 n nn 的無色串,每次可以對乙個區間染上相同的顏色。問最少多少次可以形成目標串。告訴你,這題的藍是假的,太假了,資料也太弱了。完全是個暴力選手亂碾標算用的,其實本題的時間複雜度完全可以做到 o n 3 o n 3 o n3 第一眼看資料範圍還以為是大...