zoukankan      html  css  js  c++  java
  • 【bzoj1260】[CQOI2007]涂色paint 区间dp

    题目描述

    给出一个序列,每次可以给一段染成同一种颜色,问最少要染多少次能够染成给定方案。

    输入

    输入仅一行,包含一个长度为n的字符串,即涂色目标。字符串中的每个字符都是一个大写字母,不同的字母代表不同颜色,相同的字母代表相同颜色。

    输出

    仅一行,包含一个数,即最少的涂色次数。

    样例输入

    RGBGR

    样例输出

    3


    题解

    区间dp

    设$f[i][j]$表示染$[i,j]$这段区间所需要的最小次数。

    那么当$i$和$j$颜色相同时,显然需要一起染,可以推知$f[i][j]=min(f[i-1][j+1]+1,min(f[i+1][j],f[i][j-1]))$

    当$i$和$j$颜色不同时,不能一起染,枚举中间点$k$,相当于染$[i,k]$和$[k+1,j]$两端区间,那么$f[i][j]=min{f[i][k]+f[k+1][j]}$

    时间复杂度$O(n^3)$

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 55
    using namespace std;
    int f[N][N];
    char str[N];
    int main()
    {
    	int n , i , j , k , l;
    	scanf("%s" , str + 1) , n = strlen(str + 1);
    	memset(f , 0x3f , sizeof(f));
    	for(i = 1 ; i <= n ; i ++ ) f[i][i] = 1;
    	for(l = 2 ; l <= n ; l ++ )
    	{
    		for(i = 1 ; i <= n - l + 1 ; i ++ )
    		{
    			j = i + l - 1;
    			if(str[i] != str[j])
    				for(k = i ; k < j ; k ++ )
    					f[i][j] = min(f[i][j] , f[i][k] + f[k + 1][j]);
    			else f[i][j] = min(f[i][j] , min(f[i + 1][j - 1] + 1 , min(f[i + 1][j] , f[i][j - 1])));
    		}
    	}
    	printf("%d
    " , f[1][n]);
    	return 0;
    }
    
  • 相关阅读:
    Java反射研究(3)
    Java反射研究(2)
    Java反射研究(1)
    从百度文库中复制文本的方法
    jdk/bin中的native2ascii.exe使用
    EA经典入门教程
    JSP自定义标签(3)
    JSP自定义标签(1)
    将Java doc转换为chm的方法
    多态性——vptr和vtable
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/7724520.html
Copyright © 2011-2022 走看看