HDU2476 - String painter - 区间dp+字符串处理

1.题目描述

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
2.题意概述:

给出两个串s1和s2,一次只能将一个区间刷一次,问最少几次能让s1=s2。

例如zzzzzfzzzzz,长度为11,我们就将下标看做0~10
先将0~10刷一次,变成aaaaaaaaaaa
1~9刷一次,abbbbbbbbba
2~8:abcccccccba
3~7:abcdddddcba
4~6:abcdeeedcab
5:abcdefedcab
这样就6次,变成了s2串了
第二个样例也一样
0
先将0~10刷一次,变成ccccccccccb
1~9刷一次,cdddddddddcb
2~8:cdcccccccdcb
3~7:cdcdddddcdcb
4~6:cdcdcccdcdcb
5:cdcdcdcdcdcb
最后竟串尾未处理的刷一次
就变成了串2cdcdcdcdcdcd
所以一共7次

3.解题思路:

集训时候直接把这题跳了,学长都写了hard两字orz,然后结束后参考了网上的题解,对于这种最优子结构问题可以考虑用区间dp做,把s1变成s2,关键是看它们相同的区间。dp问题还需要细嚼慢咽啊。

4.AC代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
#define maxn 101
using namespace std;
char s1[maxn], s2[maxn];
int dp[maxn][maxn], ans[maxn];
int main()
{
	while (scanf("%s%s", s1, s2) != EOF)
	{
		memset(dp, 0, sizeof(dp));
		int len = strlen(s1);
		for (int i = 0; i < len; i++)
			for (int j = i; j >= 0; j--)
			{
				dp[j][i] = dp[j + 1][i] + 1;
				for (int k = j + 1; k <= i; k++) // 从j到i中间的所有刷法
					if (s2[j] == s2[k])	// 如果j和k相同,寻找j到k和k+1到i的最佳方案
						dp[j][i] = min(dp[j][i], dp[j + 1][k] + dp[k + 1][i]);
			}
		for (int i = 0; i < len; i++)
			ans[i] = dp[0][i];			// ans记录0到i的最优解
		for (int i = 0; i < len; i++)
			if (s1[i] == s2[i])		// 如果第i个位置相同,则它不用刷
				ans[i] = ans[i - 1];
			else
				for (int j = 0; j < i; j++)	//枚举区间,取最优情况
					ans[i] = min(ans[i], ans[j] + dp[j + 1][i]);
		printf("%d\n", ans[len - 1]);
	}
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值