String painter HDU - 2476
考察:区间dp
这道题可以想到P4170涂色和Acwing 编辑距离的结合.
错误思路:
如果直接按a[i]==b[i]与a[j]==b[j]划分的话(实际上a[i]==b[i]与j可以合并),就会少了考虑b连续的条件.使得次数增加了.
错误思路2:
将a[i]==a[j]&&b[i]==b[j]与b[i]==a[i]合并起来考虑,这样思路是对的但是划分集合真的太太太太繁琐了.
正确思路:
实际上是将上面分两步进行.当a[j]==b[j]时,f[i][j] = f[i][j-1].但是当a[j]!=b[j],我们只能通过b的[i,j]区间是否有连续(即b[i]与b[j]的关系)来减少步数.
f[i][j] = min(f[i][k]+f[k+1][j],f[i][j]).
这里可以采取预处理的方式,也就是像P4170那道题一样先求出空白串->B,在考虑a[i]与b[i]的关系进行进一步的消减.当a[i]==b[i],那么i不用涂了,当a[i]!=b[i]要更新f[1][i]使得前面的更新连续到i处.
注意:f[1][i]不能改成f[1][i] = f[1][i-1]+f[i][i],因为优化点不一定在i-1点
如: axcxx aycyy
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstring> 5 using namespace std; 6 const int N = 110; 7 char a[N],b[N]; 8 int f[N][N]; 9 int main() 10 { 11 while(scanf("%s%s",a+1,b+1)!=EOF) 12 { 13 int n = strlen(a+1); memset(f,0,sizeof f); 14 for(int i=1;i<=n;i++) f[i][i] = 1; 15 for(int len=2;len<=n;len++) 16 for(int l=1;l+len-1<=n;l++) 17 { 18 int r = l+len-1; 19 f[l][r] = 0x3f3f3f3f; 20 if(b[l]==b[r]) f[l][r] = min(f[l+1][r],f[l][r-1]); 21 else 22 for(int k=l;k<r;k++) 23 f[l][r] = min(f[l][r],f[l][k]+f[k+1][r]); 24 } 25 for(int i=1;i<=n;i++) 26 { 27 if(a[i]==b[i]) 28 f[1][i] = f[1][i-1]; 29 else 30 for(int l=1;l<i;l++) 31 f[1][i] = min(f[1][l]+f[l+1][i],f[1][i]); 32 } 33 printf("%d\n",f[1][n]); 34 } 35 return 0; 36 }