http://acm.hdu.edu.cn/showproblem.php?pid=2476
String painter
Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5621 Accepted Submission(s): 2674
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.
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
题意:给你两个字符串,让你把第一个串变成第二个串,改变规则为:每次可以挑选一个区间,然后可以将区间里个每个字符都改变成同一个任意字符。问你至少要多少次,才能将第一个串变成第二个串?
思路:区间dp
因为第一个串的字母若想留下来,那么此字母则将整段字符串分为三部分,中间的一个字母留下来,两边的区间各自改变,并且不能对中间的字母进行任何操作。所以第一个字符串先不考虑,最后在统计相同的字母。
因为第一个串的字母若想留下来,那么此字母则将整段字符串分为三部分,中间的一个字母留下来,两边的区间各自改变,并且不能对中间的字母进行任何操作。所以第一个字符串先不考虑,最后在统计相同的字母。
然后就变成了涂色问题,https://cn.vjudge.net/problem/LightOJ-1422,跟这道题一模一样。
代码:
#include <cstring>
#include <stdio.h>
#include <cctype>
#include <stdlib.h>
#include <string>
#include <map>
#include <iostream>
#include <sstream>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <algorithm>
#include<list>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define inf 0x3f3f3f3f
typedef long long LL;
const int N=1e2+20;
const double pi=acos(-1);
int n,t;
char a[N],b[N];
int dp[N][N];
int main()
{
while(~scanf("%s%s",a+1,b+1))
{
n=strlen(a+1);
mem(dp,0);
for(int j=1; j<=n; j++) //dp[i][j]代表区间【i,j】最小需要 涂 的次数。
for(int i=1; i<=j; i++)
{
dp[i][j]=dp[i][j-1]+1; //将第j位涂色
for(int k=i; k<j; k++) //枚举k,表示第k位和第j位可以在一次刷色刷成,
if(b[k]==b[j])
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j-1]);//[i,k]+[k+1,j-1]+0(第j位不用刷色了,因为在刷第k位时就在j位也一块刷色了),然后[k+1,j-1]单独拿出刷色
}
for(int k=1; k<=n; k++) //dp[i][j]代表区间【i,j】最小需要 更改 的次数。
if(a[k]==b[k])//枚举可能不用刷色的位置
for(int j=k; j<=n; j++)
dp[1][j]=min(dp[1][j],dp[1][k-1]+dp[k+1][j]);//此字母将[1,j]分成三段
printf("%d\n",dp[1][n]);
}
}