【bzoj1260】[CQOI2007]涂色paint

题意:就是说一开始一个序列是空的,然后每次可以将连续的一段染成同一颜色,问多少次才能到目标状态。

 

一开始想的是二分,然后题解DP。。。

 

f[i][j]表示区间[i,j]需要染色多少次 

首先初始状态是f[i][i]=1和f[i][i+1]=str[i]==str[i+1] 

然后从短区间地推到长区间 

对于f[i][j],若str[i]==str[j],则有f[i][j]=min{f[i+1][j],f[i][j-1],f[i+1][j-1]+1},否则f[i][j]=min{f[i][k]+f[k+1][j]∣i≤k<j} 

 

复杂度:O(n^3)

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
 
#define N 60
 
int len;
int f[N][N];
 
char str[N];
 
int main()
{
    scanf("%s",str+1);
    len=strlen(str+1);
    memset(f,127/3,sizeof(f));
    for (int i=1;i<=len;i++)
        f[i][i]=1;
    for (int l=1;l<=len;l++)
        for (int i=1;i<=len-l;i++)
        {
            int j=i+l;
            if (str[i]==str[j])
                if (l==1)
                    f[i][j]=1;
                else
                {
                    f[i][j]=min(f[i+1][j],f[i][j-1]);
                    //f[i][j]=min(f[i][j],f[i+1][j-1]+1);删了这句更快,0ms。。
                }
            else
                for (int k=i;k<j;k++)
                    f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]);
        }
    printf("%d
",f[1][len]);
    return 0;
}

  

原文地址:https://www.cnblogs.com/yangjiyuan/p/5321086.html