题目
String painter
给出两个字符串s1,s2。对于每次操作可以将 s1 串中的任意一个子段变成另一个字符。问最少需要多少步操作能将s1串变为s2串。
解析
太妙了这个题,mark一下。
这个题先考虑怎么由空串转化s2, 表示从空串到s2最少的次数,
则有,
若存在一个
,使
,则
,
为断点,
和
同时刷。
然后再考虑把s1刷成s2的代价
设表示把
刷成
的次数
当时,可以不刷,显然
否则,在区间内找最小次数
代码
#include using namespace std; const int N = 1e3 + 10; int n, m; int f[N][N], sum[N]; char s[N], t[N]; int main() { while (cin >> s) { cin >> t; memset(f, 0, sizeof f); memset(sum, 0, sizeof sum); int len = strlen(s); for (int i = 0; i < len; ++i) f[i][i] = 1; for (int i = 0; i < len; ++i) for (int j = i - 1; j >= 0; --j) { f[j][i] = f[j + 1][i] + 1; for (int k = j + 1; k <= i; ++k) if (t[j] == t[k]) f[j][i] = min(f[j][i], f[j + 1][k] + f[k + 1][i]); } for (int i = 0; i < len; ++i) sum[i] = f[0][i]; if (s[0] == t[0]) sum[0] = 0; for (int i = 1; i < len; ++i) { if (s[i] == t[i]) sum[i] = min(sum[i], sum[i - 1]); else for (int j = 0; j < i; ++j) sum[i] = min(sum[i], sum[j] + f[j + 1][i]); } cout << sum[len - 1] << endl; } }