BZOJ1260 [CQOI2007]涂色paint 动态规划

欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - BZOJ1260


题意概括

  假设你有一条长度为5的木版,初始时没有涂过任何颜色。你希望把它的5个单位长度分别涂上红、绿、蓝、绿、红色,用一个长度为5的字符串表示这个目标:RGBGR。 每次你可以把一段连续的木版涂成一个给定的颜色,后涂的颜色覆盖先涂的颜色。例如第一次把木版涂成RRRRR,第二次涂成RGGGR,第三次涂成RGBGR,达到目标。 用尽量少的涂色次数达到目标。

  n<=50


题解

  我们考虑区间型动归。

  如果s[L] = s[R] ,那么显然有dp[L][R] = min(dp[L][R] , dp[L + 1][R] , dp[L][R - 1])。

  如果s[L] = s[L + 1],那么有dp[L][R] = min(dp[L][R] , dp[L + 1][R]);

  如果s[R] = s[R - 1],那么有dp[L][R] = min(dp[L][R] , dp[L][R - 1]);

  剩余的情况,就是基础的区间合并:dp[L][R]=min(dp[L][R] , dp[L][k] +dp[k+1][R] |  L <= k Λ k<R);

  所以n3复杂度。

  这题有30秒时限,貌似开大了。

  记忆化dfs也可以做的。

  初始所有的dp[i][i] = 1;


代码

#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
const int N=50+5;
int n,dp[N][N];
char s[N];
int main(){
	scanf("%s",s+1);
	n=strlen(s+1);
	memset(dp,63,sizeof dp);
	for (int i=1;i<=n;i++)
		dp[i][i]=1;
	for (int i=1;i<n;i++)
		for (int j=1;j+i<=n;j++){
			int L=j,R=j+i;
			if (s[L]==s[R])
				dp[L][R]=min(dp[L+1][R],dp[L][R-1]);
			if (s[L]==s[L+1])
				dp[L][R]=min(dp[L][R],dp[L+1][R]);
			if (s[R]==s[R-1])
				dp[L][R]=min(dp[L][R],dp[L][R-1]);
			for (int k=L;k<R;k++)
				dp[L][R]=min(dp[L][R],dp[L][k]+dp[k+1][R]);
		}
	printf("%d",dp[1][n]);
	return 0;
}

  

原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ1260.html