BZOJ1260

来源:互联网 发布:未来城网络黄金上市 编辑:程序博客网 时间:2024/05/23 12:15

1260: [CQOI2007]涂色paint

Time Limit: 30 Sec  Memory Limit: 64 MB
Submit: 588  Solved: 332
[Submit][Status]

Description

假设你有一条长度为5的木版,初始时没有涂过任何颜色。你希望把它的5个单位长度分别涂上红、绿、蓝、绿、红色,用一个长度为5的字符串表示这个目标:RGBGR。 每次你可以把一段连续的木版涂成一个给定的颜色,后涂的颜色覆盖先涂的颜色。例如第一次把木版涂成RRRRR,第二次涂成RGGGR,第三次涂成RGBGR,达到目标。 用尽量少的涂色次数达到目标。

Input

输入仅一行,包含一个长度为n的字符串,即涂色目标。字符串中的每个字符都是一个大写字母,不同的字母代表不同颜色,相同的字母代表相同颜色。

Output

仅一行,包含一个数,即最少的涂色次数。

Sample Input

Sample Output

【样例输入1】
AAAAA

【样例输入1】
RGBGR

【样例输出1】
1

【样例输出1】
3


HINT

40%的数据满足:1<=n<=10
100%的数据满足:1<=n<=50


【题解】一道DP好题,我曾试想过用贪心后来WR 了几次发现了错误,就改用DP 了。

    让我们来看一下转移方程吧:

      f[ i ][ j ],i 表示当前的段的起点,j 表示它的段长度。然后,我们为了得到它的优解,就通过一些转移。

      枚举 一个 k 将它分为两段,f[ i ][ j ]=f[ i ][ k-i+1]+f[ k+1 ][ j-k ];当然其中有一种情况就是若这一段的开头等于结尾,则在加两个个判断 :f [ i ][ j ]=min(f[ i ][ j ],min(f[ i ][ j-1 ],f[ i+1][ j-1]);


#include<cstdio>#define min(x,y) x<y?x:yint a[51],f[51][51];int main(){  char ch;int l=0,p=0;    while(ch=getchar(),ch!='\n' && ch!='\r')    {   int t=(int)ch-(int)'A'+1;   if(p!=t)a[++l]=t;   p=t; }    for(int i=1;i<=l;i++)f[i][1]=1; for(int i=2;i<=l;i++)  for(int j=1;j<=l-i+1;j++)   {  f[j][i]=f[j][1]+f[j+1][i-1];  for(int k=j+i-1;k>j;k--)     {                        int t=0,p=0;  if((k-j+1)!=i)t=f[j][k-j+1];     else if(a[j]==a[k])t=min(f[j][k-j],f[j+1][k-j]);     else continue;      if(k<j+i-1)p=f[k+1][j+i-1-k];  f[j][i]=min(f[j][i],t+p);    }      }printf("%d\n",f[1][l]);return 0;  }



0 0