uva10453 - Make Palindrome(递推+ 路径输出)

题目:uva10453 - Make Palindrome(递推+ 路径输出)

题目大意:给出一字符串,仅仅只能做增加字符的操作,问最少增加多少字符串可以是的最后的字符串变成回文。并且将这样的字符串(增加长度要是最小的)的任意一种输出。

解题思路:dp【i】【j】代表第i个字符到第j个字符之间要增加的最少的字符串。递推公式:s【i】 == s【j】, dp【i】【j】 = dp【 i + 1】【j - 1】; s【i】 != s【j】 ,dp【i][j] = min (dp[i + 1][j] + 1, dp

[i][j - 1] + 1,dp[i + 1][j - 1] + 2);

路径输出就是用递归的思想,从后往前找对应的路径,因为是回文,所以这里只存字符串的一半在ans中,长度为奇数的回文中间的那个字符也要存下来。

代码:

#include <cstdio>
#include <cstring>

const int N = 1005;
int dp[N][N];
char str[N];
char ans[N];

void init (int len) {

	for (int i = 0; i < len; i++) {

		dp[i][i] = 0;
		if (i + 1 < len) {

			if (str[i] == str[i + 1])
				dp[i][i + 1] = 0;
			else
				dp[i][i + 1] = 1;
		}
	}
}

int Min (const int a, const int b) { return a < b ? a: b; }

void printf_ans (int i, int j) {

	if (i == j) {

		ans[0] = str[i];

	} else if (j - i == 1) {

		if (str[i] == str[j]) {

			ans[0] = str[i];
		} else {

			ans[0] = str[j];
			ans[1] = str[i];
		}
	} else {

		int len = (j - i + dp[i][j]) / 2 + 1;
		if (str[i] == str[j]) {

			printf_ans(i + 1, j - 1);
			ans[len - 1] = str[i];
		} else {

			if (dp[i][j] == dp[i + 1][j] + 1) {
				printf_ans(i + 1, j);
				ans[len - 1] = str[i];
			} else if (dp[i][j] == dp[i][j - 1] + 1) {

				printf_ans(i, j - 1);
				ans[len - 1] = str[j];
			} else {

				printf_ans(i + 1, j - 1);
				ans[len - 2] = str[j];
				ans[len - 1] = str[i];
			}
		}
	}
}

int main () {

	int len;
	while (gets(str) != NULL) {

		len = strlen (str);
		if (!len) {
			printf ("0 %s\n", str);
			continue;
		}

		init (len);
		for (int n = 3; n <= len; n++) {
			for (int i = 0, j = n - 1; j < len; i++, j++) {

				if (str[i] == str[j])
					dp[i][j] = dp[i + 1][j - 1];
				else
					dp[i][j] = Min (dp[i + 1][j - 1] + 2, Min (dp[i][j - 1],dp[i + 1][j]) + 1); 

			}
		}

		printf ("%d ", dp[0][len - 1]);
		if (dp[0][len - 1] == 0)
			printf ("%s\n", str);
		else {

			printf_ans(0, len - 1);
			len += dp[0][len - 1];
			if (len % 2) {

				len /= 2;
				for (int i = len; i > 0; i--)
					printf ("%c", ans[i]);
			} else {

				len = len / 2 - 1;
				for (int i = len; i >= 0; i--)
					printf ("%c", ans[i]);
			}

			ans[len + 1] = '\0';
			printf ("%s\n", ans);
		}
	}
	return 0;
}

uva10453 - Make Palindrome(递推+ 路径输出)

时间: 2024-08-29 21:42:57

uva10453 - Make Palindrome(递推+ 路径输出)的相关文章

UVA - 624CD(递推+ 路径打印)

题目: UVA - 624CD(递推+ 路径打印) 题目大意:给出一组数据,给定一个N,问这些数据能否拼凑出不大于N的最接近N的数据,可以的话输出最接近N的数据,并且打印出最长路径(要求要找输入的顺序). 解题思路:dp[j]:代表凑出J这个数值最多需要几个数.d[j] = Max (d[j - v[i]] + 1. 打印路径,如果取得是最小值,那么顺着dp标记的值的减小就可以找到路径,但是取的是最大值,这样它的下一个并不能直接靠dp数组的值来判断,而是要判断到最后是否最终的值等于0.用回溯.

uva11151Longest Palindrome(递推)

题目;uva11151Longest Palindrome(递推) 题目大意:给出一个字符串,问它可以通过去掉些字符得到的最长的回文的长度. 解题思路:dp[i][j]代表从字符串i位到j位最长的回文的长度. 如果s[i] == s[j] , dp[i][j] = dp[i - 1][j - 1] + 2: 因为头尾相同,那么要求i到j的最长的回文的话,只有可能是中间的部分最长的回文加上2. 否则dp[i][j] = Max (dp[i][j - 1], dp[i + 1][j]): 计算顺序:

uva10739String to Palindrome(递推)

题目:String to Palindrome 题目大意:给出一字符串,给你三种操作:可以将任何位置的字符删除,可以将任何位置的字符替换,可以在任何位置插入一个字符.问最少的操作能够把这个字符转换成回文. 解题思路:dp[i][j]代表使字符串i到j位的子串变成回文的最少的操作.替换和删除还算好做,一开始一点都不知道插入该怎么办,后来看了别人的题解发现删除和插入是一样的效果.例如对于abbb字符串中的位置(1234)这个串,如果删除最后的那个b,那么就是dp[1][3] + 1.如果是在a的前面

uva662 - Fast Food(递推)

题目:uva662 - Fast Food(递推) 题目大意:要求在同一条路上的N家快餐店,新建K个补助站点,每个快餐店和它的补助站点的距离之和最小.并且输出路径. 解题思路:这题之前想了很久,但是却漏掉最重要的一点:一条路上[1,N]快餐店,建一个补助站的话,建在中间是最优的.那么对于一个补助站是这样的,对于两个补助站的话,就看这两个补助站提供补助的范围了.dp[k][j]表示在前j家快餐店建了k个补助站最小的补助距离.dp[k][j] = Min (dp[k - 1][i] + s[i +

UVA - 348Optimal Array Multiplication Sequence(递推)

题目:Optimal Array Multiplication Sequence 题目大意:给出N个矩阵相乘,求这些矩阵相乘乘法次数最少的顺序. 解题思路:矩阵相乘不满足交换率但满足结合率.dp[i][j] 代表第1个矩阵到第j个矩阵之间的最少的乘法次数,转移状态方程:dp[i][j] = Min(dp[i][k] + dp[k + 1][j]  + A[i - 1] * A[k] *A[j]) k>= i && k <= j - 1.A0A1A2A3..Ak  |  Ak+1

HDU2067/HDU1267 递推

小兔的棋盘 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 9447    Accepted Submission(s): 4879 Problem Description 小兔的叔叔从外面旅游回来给她带来了一个礼物,小兔高兴地跑回自己的房间,拆开一看是一个棋盘,小兔有所失望.不过没过几天发现了棋盘的好玩之处.从起点(0,0)走到终点(n

URAL 1183 Brackets Sequence DP 路径输出

题意:长度小于100的字符串s只由四种字符"()[]"组成,求以该串为子串的最短的合法串.合法串递归定义为: (1)空串合法 (2)如果S合法,则(S).[S]合法 (3)如果A.B合法,则AB合法 思路: 设dp[i][j]为s(i,j)变为合法串后,合法串的长度或需要添加的字符的个数,状态转移: (1)如果s[i]和s[j]匹配,dp[i,j]=dp[i+1,j-1]. (2)如果不匹配,划分s(i,j)为s(i,k)和s(k+1,j),划分后dp[i,j]=dp[i,k]+dp[

算法--递推策略

本文地址:http://www.cnblogs.com/archimedes/p/4265019.html,转载请注明源地址. 递推法是一种重要的数学方法,在数学的各个领域中都有广泛的运用,也是计算机用于数值计算的一个重要算法.这种算法特点是:一个问题的求解需一系列的计算,在已知条件和所求问题之间总存在着某种相互联系的关系,在计算时,如果可以找到前后过程之间的数量关系(即递推式),那么,从问题出发逐步推到已知条件,此种方法叫逆推.无论顺推还是逆推,其关键是要找到递推式.这种处理问题的方法能使复杂

uva10564 - Paths through the Hourglass(递推)

题目:uva10564 - Paths through the Hourglass(递推) 题目大意:给出这样的两个数塔,然后给出一个值,问你能否从这个数塔中找到路径,路径上的值之和等于这个数,输出这样的路径的总数,如果多条打印路径先挑开始的位置(0..n - 1)最小的,如果这样还是有多条,在比较后面的向左向右字典序最小的. 解题思路:一开始两个数塔一个正着推,一个倒着推,结果数目是出来了,但是路径就难办了,最后把这两个数塔都正着推,只是状态转移方程不一样.这样路径输出就比较好处理. 代码: