假設你有一條長度爲5的木版,初始時沒有塗過任何顏色。你但願把它的5個單位長度分別塗上紅、綠、藍、綠、紅色,用一個長度爲5的字符串表示這個目標:RGBGR。 每次你能夠把一段連續的木版塗成一個給定的顏色,後塗的顏色覆蓋先塗的顏色。例如第一次把木版塗成RRRRR,第二次塗成RGGGR,第三次塗成RGBGR,達到目標。 用盡可能少的塗色次數達到目標。html
Input
輸入僅一行,包含一個長度爲n的字符串,即塗色目標。字符串中的每一個字符都是一個大寫字母,不一樣的字母表明不一樣顏色,相同的字母表明相同顏色。ios
Output
僅一行,包含一個數,即最少的塗色次數。spa
1.首先咱們先把數列收縮一下:由於一段連續的同色只需被刷一次,而後對應位置的表置爲1;code
2.考慮DP。htm
if(list[l]==list[r])f[l][r]=min(f[l][r-1],f[l+1][r]);
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; string s; bool use[27]; int num[27],list[110],f[110][110]; int main(){ cin>>s; memset(f,0x3f,sizeof(f)); for(int i=0;i<s.size();++i){ while(s[i]==s[i+1])++i; if(use[s[i]-'A'+1])list[++list[0]]=num[s[i]-'A'+1]; else{ use[s[i]-'A'+1]=1; num[s[i]-'A'+1]=++num[0]; list[++list[0]]=num[0]; } f[list[0]][list[0]]=1; } for(int len=2;len<=list[0];++len) for(int l=1;l<=list[0]-len+1;++l){ int r=l+len-1; if(list[l]==list[r])f[l][r]=min(f[l][r-1],f[l+1][r]); 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][list[0]]); return 0; }
有關區間DP的其餘講解參考個人隨筆:http://www.cnblogs.com/COLIN-LIGHTNING/p/9038198.htmlblog