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; }