P4170 [CQOI2007]涂色 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
设DP[i][j]为完成(i-j)区间的最少涂鸦次数。
考虑dp[i][j]的转移:
重点:如果s[i]==s[j],dp[i][j]=min(dp[i][j-1],dp[i+1][j]),因为颜色一样,只需要首次涂色的时候多图一个。
那为什么不是dp[i][j]=dp[i-1][j+1]+1呢?举例:RRWRR dp[1][5]!=dp[2][4]+1。
其他正常区间dp转移即可.
初始化:dp[i][i]=1.
#include<bits/stdc++.h> using namespace std; #define ll long long #define mp make_pair #define pb push_back #define popb pop_back #define fi first #define se second const int N=110; //const int M=; const int inf=0x3f3f3f3f; //const ll INF=0x3ffffffffffff; int T,n,dp[N][N]; char s[N]; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } int main() { // freopen("","r",stdin); // freopen("","w",stdout); scanf("%s",s+1); n=strlen(s+1); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) dp[i][j]=inf; for(int i=1;i<=n;i++) dp[i][i]=1; for(int len=2;len<=n;len++) for(int i=1;i+len-1<=n;i++) { int j=i+len-1; if(s[i]==s[j]) dp[i][j]=min(dp[i][j-1],dp[i+1][j]); for(int k=i;k<j;k++) dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]); } printf("%d",dp[1][n]); return 0; }