想破脑袋想不出来,看神犇txh那么快切了还以为是道水题,真的不看题解完全想不出QAQ,贴学长题解
对于有重叠部分刷法的处理:
先刷区间[1,5]再刷[3,7]<=====>先刷[1,2],再刷[3,7]
因此,只需考虑不相交的刷法
1、首先考虑石头都没有颜色刷到B:
思想与C题相同,保证最优解的刷法能够被我们的区间DP状态转移方程转移即可
f[i][j]=min{f[i][k]+f[k+1][j],f[i][j-1]}; f[i][j-1]只有在b[i]==b[j]时才考虑转移
2、再考虑如何从初始状态A刷到状态B,做一次普通DP:
dp[i]:前i个石头刷成最终状态的最少次数
对于当前考虑的第i个石头
1、如果和a[i]==b[i],可以考虑不用刷i
2、在[1,i-1]中枚举刷的起点k,将[k,i]当做没有颜色来刷成B状态
dp[i]=min{dp[k-1]+f[k][i]}
a[i]==b[i]时加一次决策:dp[i]=min(dp[i],dp[i-1])其实可以直接=dp[i-1],因为大区间由小区间跟新,f[k][i]>=f[k][i-1],所以dp[i-1]一定<=最优解
#include<cstdio>
#include<cstring>
#define maxl 110
int n;
int sum[maxl],ans[maxl];
int f[maxl][maxl];
char a[maxl],b[maxl];
void prework()
{
memset(f,0,sizeof(f));
n=strlen(a+1);
}
int min(int a,int b)
{
if(a<b)
return a;
else
return b;
}
void mainwork()
{
for(int j=1;j<=n;j++)
for(int i=j;i>=1;i--)
{
f[i][j]=f[i+1][j]+1;
for(int k=i+1;k<=j;k++)
if(b[i]==b[k])
f[i][j]=min(f[i][j],f[i+1][k]+f[k+1][j]);
//由k处顺便把i处刷掉,所以f[i+1][k]
//注意这里访问到i+1,k+1,数组不能只开101
}
for(int i=1;i<=n;i++)
ans[i]=f[1][i];
for(int i=1;i<=n;i++)
if(a[i]==b[i])
ans[i]=ans[i-1];
else
for(int j=1;j<i;j++)
ans[i]=min(ans[i],ans[j]+f[j+1][i]);
}
void print()
{
printf("%d\n",ans[n]);
}
int main()
{
while(~scanf("%s%s",a+1,b+1))
{
prework();
mainwork();
print();
}
return 0;
}