Palindrome
Problem Description
A palindrome is a symmetrical string, that is, a string read identically from left to right as well as from right to left. You are to write a program which, given a string, determines the minimal number of characters to be inserted into the string in order
to obtain a palindrome.
As an example, by inserting 2 characters, the string "Ab3bd" can be transformed into a palindrome ("dAb3bAd" or "Adb3bdA"). However, inserting fewer than 2 characters does not produce a palindrome.
As an example, by inserting 2 characters, the string "Ab3bd" can be transformed into a palindrome ("dAb3bAd" or "Adb3bdA"). However, inserting fewer than 2 characters does not produce a palindrome.
Input
Your program is to read from standard input. The first line contains one integer: the length of the input string N, 3 <= N <= 5000. The second line contains one string with length N. The string is formed from uppercase letters from 'A' to 'Z', lowercase letters
from 'a' to 'z' and digits from '0' to '9'. Uppercase and lowercase letters are to be considered distinct.
Output
Your program is to write to standard output. The first line contains one integer, which is the desired minimal number.
Sample Input
5 Ab3bd
Sample Output
2呜呜还是不知道格式怎么搞····那就在这里面写了题意:问你再填几个字符形成回文字符串,最开始的我的想法是枚举,分奇数还是偶数n,可是发现枚举的不一定是最小的,如果你枚举一个位置,整体字符串就会发生变化,这道题的正解是DP LCS做法:先把字符串翻过来,与原字符串求LCS 这样求出的值用n - dp[n][n]就是最小值了,如果不知道为什么,画画图就会发现。注意:这里面dp数组正常时5000*5000,这样会MTL,我们应用了滚动数组。先贴个连接http://blog.youkuaiyun.com/niushuai666/article/details/6677982PS:小牛的博客还是拜读了好多的 :)滚动数组的作用在于优化空间,主要应用在递推或动态规划中(如01背包问题)。因为DP题目是一个自底向上的扩展过程,我们常常需要用到的是连续的解,前面的解往往可以舍去。所以用滚动数组优化是很有效的。利用滚动数组的话在N很大的情况下可以达到压缩存储的作用。这里主要应用了无后效性,当前状态只与前一个或者前两个状态有关。滚动数组实际是一种节省空间的办法,时间上没啥优势,多用于DP中,举个例子吧:一个DP,平常如果需要1000×1000的空间,其实根据DP的无后效性,可以开成2×1000,然后通过滚动,获得和1000×1000一样的效果。滚动数组常用于DP之中,在DP过程中,我们在由一个状态转向另一个状态时,很可能之前存储的某些状态信息就已经无用了,例如在01背包问题中,从理解角度讲我们应开DP[i][j]的二维数组,第一维我们存处理到第几个物品,也就是阶段了,第二维存储容量,但是我们获得DP[i],只需使用DP[i - 1]的信息,DP[i - k],k>1都成了无用空间,因此我们可以将数组开成一维就行,迭代更新数组中内容,滚动数组也是这个原理,目的也一样,不过这时候的问题常常是不可能缩成一维的了,比如一个DP[i][j]需要由DP[i - 1 ][k],DP[i - 2][k]决定,i<n,0<k<=10;n <= 100000000;显然缩不成一维,正常我们应该开一个DP[100000005][11]的数组,结果很明显,超内存,其实我们只要开DP[3][11]就够了DP[i%3][j]由DP[(i - 1)%3][k]和DP[(i - 2)%3][k]决定,空间复杂度差别巨大。
学习了·····
#include<iostream> #include<cstdio> #include<string.h> #include<string> #include<set> #include<algorithm> #include<cmath> #include<stdlib.h> #define ll __int64 #define MAX 1000009 using namespace std; int dp[2][5009]; int solve_dp(char* x,char* y,int n) { int i,j; int now,pre; memset(dp,0,sizeof(dp));//³õʼ»¯ for(i = 1;i<=n;i++) { for(j = 1;j<=n;j++) { now = i%2; pre = 1 - now ; if(x[i-1]==y[j-1]) dp[now][j] = dp[pre][j-1] + 1; else dp[now][j] = max(dp[now][j-1],dp[pre][j]); } } return dp[n%2][n]; } int main() { char a[5009],b[5009]; int n; while(~scanf("%d",&n)) { scanf("%s",a); strcpy(b,a); strrev(a); int ans = solve_dp(a,b,n); printf("%d\n",n-ans); } return 0; }