[CQOI2007]涂色PAINT
[CQOI2007]涂色PAINT
https://ac.nowcoder.com/acm/problem/19909
题目描述
假设你有一条长度为5的木版,初始时没有涂过任何颜色。你希望把它的5个单位长度分别涂上红、绿、蓝、绿、红色,用一个长度为5的字符串表示这个目标:RGBGR。 每次你可以把一段连续的木版涂成一个给定的颜色,后涂的颜色覆盖先涂的颜色。
例如第一次把木版涂成RRRRR,第二次涂成RGGGR,第三次涂成RGBGR,达到目标。 用尽量少的涂色次数达到目标。
输入描述:
输入仅一行,包含一个长度为n的字符串,即涂色目标。
字符串中的每个字符都是一个大写字母,不同的字母代表不同颜色,相同的字母代表相同颜色。
输出描述:
仅一行,包含一个数,即最少的涂色次数。
题解
区间dp
显然对于一个区间,只能是由它的子区间再往左涂一次或者再往右涂一次
所以对于一个大于2的区间都可以分成两个子区间来考虑
对于区间l到r
如果s[l]==s[r], 那么涂了l的时候,也一定同时涂上了r
也就是说,转移方程在s[l]==s[r]下为dp[l][r]=min(dp[l+1][r],dp[l][r-1])
如果s[l],s[r]不一样
那么此区间的涂色就可以拆分成两个区间的涂色次数相加
那么我们枚举断点k,此时转移方程为dp[l][r]=min(dp[l][k]+dp[k+1][r],dp[l][r])
代码
#include<iostream> #include<algorithm> #include<map> #include<vector> #include<set> #include<string> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #include<stack> using namespace std; #define ll long long #define ull unsigned long long #define pb push_back #define pii pair<int,int> #define all(A) A.begin(), A.end() #define fi first #define se second #define MP make_pair #define rep(i,n) for(register int i=0;i<(n);++i) #define repi(i,a,b) for(register int i=int(a);i<=(b);++i) #define repr(i,b,a) for(register int i=int(b);i>=(a);--i) template<typename T> inline T read(){ T s=0,f=1; char ch = getchar(); while(!isdigit(ch)) {if(ch == '-') f=-1;ch = getchar();} while(isdigit(ch)) {s=(s<<3)+(s<<1)+ch-48;ch = getchar();} return s*f; } #define gn() read<int>() #define gl() read<ll>() template<typename T> inline void print(T x) { if(x<0) putchar('-'), x=-x; if(x>9) print(x/10); putchar(x%10+'0'); } //////////////////////////////////////////////////////////////////////// const int N=360; int dp[55][55]; //////////////////////////////////////////////////////////////////////// int main(){ string s; cin>>s; int len=s.length(); s="&"+s; memset(dp,0x3f,sizeof(dp)); for(int i=1;i<=len;++i)dp[i][i]=1; for(int l=2;l<=len;++l){ for(int i=1;i+l-1<=len;++i){ int j=i+l-1; if(s[i]==s[j])dp[i][j]=min(dp[i+1][j],dp[i][j-1]); else { for(int k=i;k<j;++k){ dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]); } } } } cout<<dp[1][len]<<endl; } /** * In every life we have some trouble * When you worry you make it double * Don't worry,be happy. **/
每日一题 文章被收录于专栏
每日一题题解,在做题过程中不断提升