1260. [CQOI2007]涂色【区间DP】

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

一开始想的是对于区间x,y,如果两端颜色相等dp[x][y]=dp中间那段不相等的+1
但这么做并不能涵盖所有情况,状态可能有中断
所有当两端相同时,dp[x][y]=min(dp[x][y-1],dp[x+1][y])即可
若不相同就划分成两个区间,取和的最小值。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 char a[101];
 6 int n,dp[101][101];
 7 int main()
 8 {
 9     scanf("%s",a);
10     n=strlen(a);
11     memset(dp,0x3f,sizeof(dp));
12     for (int i=0; i<n; ++i) dp[i][i]=1;
13     for (int i=2; i<=n; ++i) //区间长度
14         for (int j=0; j<n-i+1; ++j) //左端点
15         {
16             int x=j,y=j+i-1;
17             if (a[x]==a[y])
18                 dp[x][y]=min(dp[x][y-1],dp[x+1][y]);
19             else
20                 for (int k=x; k<=y-1; ++k)
21                     dp[x][y]=min(dp[x][y],dp[x][k]+dp[k+1][y]);
22         }
23     printf("%d",dp[0][n-1]);
24 }
原文地址:https://www.cnblogs.com/refun/p/8680753.html