题意:
给你一串由大写字符组成的长度为(n)字符串,现在你每次可以让区间([l,r])的所有字符变成任意一种字符。现在问你把一个长度为(n)的空串变为指定的字符串需要多少多少次操作。
分析:
这个问题在基础区间dp中夹杂了贪心的思想。
我们考虑(dp[l][r])为区间([l,r])进行染色取得了对应的值的最小的操作数。在此基础上,我们贪心的考虑,对于一个大的区间([l,r]),倘若区间两端的字符是相同的,即(str[l]==str[r]),要使得答案更优,则这个大的区间只需要通过子区间([l+1,r])或者子区间([l,r-1]),通过染成同一种颜色,花费(1)点代价转移而来。而倘若区间两端的字符不相同,则这段区间是由这段区间的两个子区间转移而来的,此时我们只需要用最基本的区间dp的讨论,通过枚举断点(k)进行状态转移。
代码:
#include <bits/stdc++.h>
#define maxn 105
using namespace std;
int dp[maxn][maxn],a[maxn];
char str[maxn];
const int inf=0x3f3f3f3f;
int main()
{
scanf("%s",str+1);
int n=strlen(str+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 p=1;p<=n;p++){
for(int i=1,j=i+p;j<=n&&i<=n;i++,j=i+p){
if(str[i]==str[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]);
}
}
}
printf("%d
",dp[1][n]);
return 0;
}