String painter
Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 11069 Accepted Submission(s): 5416
The first line contains string A.
The second line contains string B.
The length of both strings will not be greater than 100.
解析 :
可以先将一个空串转化成B,再比较与将A直接转化成B那个更快;
子集划分:令dp[i][j]为将[i, j]区间转换成功最少操作数;
最坏的情况下,是将每个字符都变一下,dp[i][i]=1;区间[i, i+1]是由[i, i]扩展来的,dp[i][i+1]=dp[i][i]+1;同理:dp[i][j]=dp[i][j-1]+1;然后在区间[i, j]中如果有一个B[k]==B[j]那么dp[i][j]=min(dp[i][j], dp[i][k-1]+dp[k][j-1]);这一步是如何来的呢?
[i, j]区间可以看作[i, k-1]+[k, j-1],当B[j]==B[k]时,所以先[k, j]全转换成1种字符,再将[k+1, j-1]转换,相当于只转化了[k, j-1];
注意,这里不要写成dp[k+1][j-1]+1, 因为dp[k][j-1]可能更小;
ans[i]表示A的[1, i]区间转换成B的[1, i]的最少操作
ans[i]=min(ans[i], ans[k]+dp[k+1][i])(0<=k<=i);
#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<math.h>
#include<map>
using namespace std;
typedef long long LL;
const int N = 1e2 + 5;
int n;
char a[N], b[N];
int f[N][N],ans[N];
int main() {
while (scanf("%s%s",a+1,b+1)!=EOF) {
n = strlen(a+1);
memset(f, 0, sizeof f);
for (int i = 1; i <= n; i++)
f[i][i] = 1;
for (int len = 2; len <= n; len++) {
for (int i = 1; i + len - 1 <= n; i++) {
int j = i + len - 1;
f[i][j] = f[i][j-1] + 1;
for (int k = i-1; k < j; k++) {
if (b[k] == b[j])
f[i][j] = min(f[i][j], f[i][k-1] + f[k][j - 1]);
}
}
}
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[j] + f[j + 1][i], ans[i]);
}
}
}
cout << ans[n] << endl;
}
return 0;
}