zoukankan      html  css  js  c++  java
  • 小明的喷漆计划(区间DP) 题解

    原题链接:LUOGU

    题目描述

    小明极其喜欢涂鸦,总是在墙上涂上各种颜色的漆。
    现在小明得到一个任务,需要喷涂一段空白围墙,且单位长度内的颜色都是相同的。小明有一种喷涂工具,它可以给任意长度的一段墙面涂上任意颜色的漆,这样的操作计为一次操作。小明要完成这个任务,又想使得操作次数尽量少,就请你帮他解决这个问题吧。

    输入

    有多组输入数据。
    每组包含一个长度不超过100的字符串(均由小写字母组成),代表需要涂鸦的墙面目标状态。

    输出

    至少需要几次操作,可达到目标。

    样例输入

    aaaaaa
    fedcbaabcdef
    aaabbbbb
    aaabbbaaa

    样例输出

    1
    6
    2
    2

    题解

    还是区间dp。
    从最小的开始,假设只有(1)a,需要1次。
    假设有(2)个,则有两种情况:
    1.为aa,显然为(1)次。
    2.为ab,显然为(2)次。
    可以得到规律:
    如果(a[l] == a[r]),则 (dp[l][r] = min(dp[l][r] , dp[l][k] + dp[k+1][r] - 1)),其中(k)为区间dp的断点。
    如果(a[l] != a[r]),则 (dp[l][r] = min(dp[l][r] , dp[l][k] + dp[k+1][r])),其中(k)为区间dp的断点。
    以上可以简化为:直接计算(dp[l][r] = min(dp[l][r] , dp[l][k] + dp[k+1][r])),后判断如果相等则--

    可以写dfs或者递推。本人喜欢递推所以有以下代码:

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int INF = 0x3f3f3f3f , N = 1e2+5;
    char a[N];int dp[N][N],n;
    
    signed main(){
    	while(scanf("%s",a + 1) != EOF){
    		n = strlen(a + 1);
    		memset(dp,0x3f,sizeof(dp));
    		for(int len = 1 ; len <= n ; len ++)
    			for(int l = 1 ; l + len - 1 <= n ; l ++){
    				int r = l + len - 1 ;
    				if(l == r)dp[l][r] = 1;
    				else{
    					for(int k = l ; k < r ; k ++)
    						dp[l][r] = min(dp[l][r] , dp[l][k] + dp[k+1][r]); 
    					if(a[l] == a[r])dp[l][r] --;
    				}
    			}
    		printf("%d
    ",dp[1][n]);
    		break;
    	}
    	return 0;
    }
    
  • 相关阅读:
    13点睛Spring4.1-Spring EL
    12点睛Spring4.1-Spring Aware
    11点睛Spring4.1-Property Editor
    10点睛Spring4.1-Application Event
    09点睛Spring4.1-AOP
    08点睛Spring4.1-Profile
    07点睛Spring4.1-BeanPostProcessor
    06点睛Spring4.1-Bean的初始化和销毁
    05点睛Spring4.1-国际化
    Solaris 11 配置IP地址
  • 原文地址:https://www.cnblogs.com/Shinomiya/p/14529698.html
Copyright © 2011-2022 走看看