HDU2476 String painter —— 区间DP

题目链接:https://vjudge.net/problem/HDU-2476

String painter

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


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
 
Recommend
lcy

题意:

给出A字符串和B字符串。每次操作可以把A串某个区间的字符变成同一种字符(自己选),问最少需要操作多少次,就能把A串变成B串?

题解:

1.先求出把一个空白串刷成B串所需要的最少操作次数,并且不仅仅是整个区间的最少操作次数需要记录,而且每个子区间的最少操作次数也需要记录。记录在dp[l][r]数组中。(怎么用最少的操作次数把空白串刷成目标串?LightOJ - 1422 Halloween Costumes

2.A串与空白串所不同的地方在于:A串在某些地方可能与B串相同,在这些地方,A串就不要再去刷了,而空白串则必须要刷。所以A串的最少操作次数就可以这样求:

 从第一个位置开始递推,假设当前递推到第i个位置。

1) 如果在第i个位置上,A串与B串相同,那么在i处就不需要处理,直接 f[i] = f[i-1] 。

2) 如果在第i个位置上,A串与B串不同,那么表明第i个字符必须刷,要刷的话,就要考虑刷多少,即需要考虑往前刷多少个?枚举取最优值。

3.一开始想用记忆化搜索去写把空串刷成B串的。但由于要利用dp[][]数组,而记忆化搜索又不能把所有信息都准确记录到dp数组上(如l>r时或者下标越界时),所以就写成递推的形式。

4.疑问:为什么可以从第一个位置开始递推,而不是也如上面那样要每个子区间都要求出来?原理是什么?跟这个相似吗?SCUT125 华为杯 D.笔芯回文

代码如下:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <vector>
 6 #include <cmath>
 7 #include <queue>
 8 #include <stack>
 9 #include <map>
10 #include <string>
11 #include <set>
12 using namespace std;
13 typedef long long LL;
14 const int INF = 2e9;
15 const LL LNF = 9e18;
16 const int MOD = 1e9+7;
17 const int MAXN = 100+10;
18 
19 char a[MAXN], b[MAXN];
20 int dp[MAXN][MAXN], f[MAXN];
21 
22 int main()
23 {
24     while(scanf("%s%s",a+1, b+1)!=EOF)
25     {
26         int n = strlen(a+1);
27         memset(dp, 0, sizeof(dp));
28 
29         for(int i = 1; i<=n; i++)
30             dp[i][i] = 1;
31         for(int len = 2; len<=n; len++) //先求出把空串刷成目标串所需要的最少次数
32         {
33             for(int l = 1; l<=n-len+1; l++)
34             {
35                 int r = l+len-1;
36                 dp[l][r] = 1+dp[l+1][r];
37                 for(int k = l+1; k<=r; k++)
38                     if(b[l]==b[k])
39                         dp[l][r] = min(dp[l][r], dp[l][k-1]+dp[k+1][r]);
40             }
41         }
42 
43         f[0] = 0;
44         for(int i = 1; i<=n; i++)   //再求出已有串刷成目标串的最少次数。
45         {
46             f[i] = i;    //初始化一下
47             if(a[i]==b[i]) f[i] = f[i-1];   //如果已有串与目标串在i处相等,则此处可以不用处理,这就是空串与已有串不同的地方
48             else for(int k = 1; k<=i; k++)   //否则,就要对i处进行刷色。刷多少呢?可知终点为i,枚举起点k,取最优值。
49                 f[i] = min(f[i], f[k-1]+dp[k][i]);
50         }
51         printf("%d
", f[n]);
52     }
53 }
View Code
原文地址:https://www.cnblogs.com/DOLFAMINGO/p/7940407.html