1260: [CQOI2007]涂色paint
Time Limit: 30 Sec Memory Limit: 64 MBSubmit: 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
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;
}