String painter,区间dp

Problem - 2476 (hdu.edu.cn)

String painter

Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 11069    Accepted Submission(s): 5416


 

Problem Description
There are two strings A and B with equal length. Both strings are made up of lower case letters. Now you have a powerful string painter. With the help of the painter, you can change a segment of characters of a string to any other character you want. That is, after using the painter, the segment is made up of only one kind of character. Now your task is to change A to B using string painter. What’s the minimum number of operations?
 

Input
Input contains multiple cases. Each case consists of two lines:
The first line contains string A.
The second line contains string B.
The length of both strings will not be greater than 100.
 

Output
A single line contains one integer representing the answer.
 

Sample Input
 
 
zzzzzfzzzzz
abcdefedcba
abababababab
cdcdcdcdcdcd
 

Sample Output
 
 
6
7
 

Source

解析 :

可以先将一个空串转化成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;
}

posted @ 2023-11-25 16:32  Landnig_on_Mars  阅读(4)  评论(0编辑  收藏  举报  来源