BZOJ1260

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:y

int 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;				  
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值