【QED】fufu犯错力

题目描述

啊呜,雪雪昨天晚上玩得很晚才睡觉,所以今天上课迟到了。作为雪雪的监护人,你决定给雪雪一个小小的处罚,让她长长记性,使她意识到时间的珍贵!

你有一个项链。但是,项链上的珍珠颜色各异,你觉得不好看。因此你把项链给拆开了。你想过把项链上的所有珍珠改成一种颜色,但是由于各种原因一直拖到了现在。

因此,需要让雪雪把项链上所有珍珠的颜色变得一致的你,给了雪雪一个神奇的道具。

这个道具可以让项链的一段区间内所有珍珠的颜色变成使用者想要的颜色! 如果只有这样,那么雪雪完全可以选择项链上的所有珍珠变成一个颜色,这样是太快了,是不行的!你在项链上选择的那段区间内所有珍珠的颜色必须一致,这样道具才可以发挥作用。

雪雪知道错了,但是雪雪还是想尽快完成你交给她的任务。你也很心疼雪雪,所以你给了她一个提示,你告诉了她最少需要使用多少次道具就可以将项链上所有珍珠颜色一致。

输入格式

输入有两行。第一行输入一个整数 n n n ,代表项链的长度。第二行输入一个长度为 n n n 的小写字符串,即项链原来的颜色。

输出格式

仅一行,包含一个整数,即最少的道具使用次数。

测试样例

5
abcba
2
7
abcbabc
4

样例说明

样例一,我们可以先选择区间 [ 3 , 3 ] [3, 3] [3,3]变成颜色 b b b,再选择区间 [ 2 , 4 ] [2, 4] [2,4]变成颜色 a a a,只需要操作两步就可以做到。

数据范围

100 % 100\% 100%的数据满足 1 ≤ n ≤ 800 1≤n≤800 1n800

其它

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

思想

这道题目是一个比较难想的动态规划,我们假设一个二维数组 d p [ i ] [ j ] dp[i][j] dp[i][j],表示区间 [ i , j ] [i,j] [i,j]转化为完全相同的字母所需要的次数为 d p [ i ] [ j ] dp[i][j] dp[i][j]对应的值,然后我们可以根据状态的转移写出下面的方程:
当位置 i i i和位置 j j j所对应的字母值是相同且 i i i j j j不相等的时候,方程如下:
d p [ i ] [ j ] = m i n ( d p [ i + 1 ] [ j ] , d p [ i ] [ j − 1 ] ) dp[i][j]=min(dp[i+1][j],dp[i][j-1]) dp[i][j]=min(dp[i+1][j],dp[i][j1])
当位置 i i i和位置 j j j所对应的字母值是不同且 i i i j j j不相等的时候,方程如下:
d p [ i ] [ j ] = m i n ( d p [ i ] [ j ] , d p [ i ] [ k ] , d p [ k + 1 ] [ j ] + 1 ) ( k 表示 [ i , j )之间的值 ) dp[i][j]=min(dp[i][j],dp[i][k],dp[k+1][j]+1)(k表示[i,j)之间的值) dp[i][j]=min(dp[i][j],dp[i][k],dp[k+1][j]+1)(k表示[i,j)之间的值)

核心代码

#include <iostream>
using namespace std;

const int N = 810;
int n, dp[810][810];
char s[810];
int min(int a, int b) {
	return a < b ? a : b;
}
int main() {
	scanf("%d%s", &n, s+1);
	memset(dp, 0x3f, sizeof(dp));
	for (int i = 1; i <= n; i++) dp[i][i] = 0;
	for (int i = 2; i <= n; i++)
	    for (int j = 1; i + j - 1 <= n; j++) {
	    	int k = i + j - 1;
	    	if (s[j] == s[k]) dp[j][k] = min(dp[j+1][k], dp[j][k-1]);
	    	else {
	    		for (int l = j; l < k; l++)
	    		    dp[j][k] = min(dp[j][k], dp[j][l] + dp[l+1][k] + 1);
			}
		}
	printf("%d\n", dp[1][n]);
	return 0;
}
  • 18
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

想要AC的dly

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值