这道题对于区间进行涂色,就往区间dp上想。

  区间dp肯定是从小区间合并到大区间,所以状态就写出来了。即dp[ i ][ j ]代表从 i 到 j 的区间中的最小方案数。

  同时,在每一次取 i 和 j 的时候,我们在 i 到 j 中枚举 k ,借此来枚举所有的区间分割情况。

  所以dp方程即为dp[ i ][ j ] = min ( dp[ i ][ j ] , dp[ i ][ k ] + dp[ k + 1][ j ]);

  同时我们要考虑尽量的删减涂色的次数。而当一段区间两端颜色相同时,我们不需要分别涂两端,而是先涂一笔,再在两端区间内涂色即可。所以如果当第 i 个颜色和第 j 个颜色相同时,我们将dp[ i ][ j ] - -;

  代码如下:

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 int n,dp[1005][1005];
 7 char c[1005];
 8 int main()
 9 {
10     scanf("%s",c);
11     n = strlen(c);
12     for(int i=0; i<n; i++)
13     for(int j=0; j<n; j++)
14     dp[i][j] = 100000005;
15     for(int i=0; i<n; i++) dp[i][i] = 1;
16     for(int i=1; i<n; i++)
17     {
18         for(int j=0; j<n; j++)
19         {
20             for(int k=j; k<i+j; k++)
21             {
22                 dp[j][i+j] = min(dp[j][k]+dp[k+1][i+j],dp[j][j+i]);
23             }
24             if(c[j] == c[i+j]) dp[j][i+j]--;
25         //    printf("%d %d %d\n",j,i+j,dp[j][j+i]);
26         }
27     }
28     printf("%d",dp[0][n-1]);
29     return 0;
30 }