求最少补多少个字符使所给字符串变成回文,直接dp,dp[i][j]代表从i到j的字串中最少补的字符。1、如果a[i]==a[j],dp[i][j]=dp[i+1][j-1],不用加新字符的情况;2、如果a[i]!=a[j],dp[i][j]=min(dp[i+1][j],dp[i][j-1])+1,在中间字符串的基础上再补一个字符;n的范围是5000二维会超内存,这里注意每次dp[i][j]的更新都用到dp[i+1]和dp[i][j-1],j-1可以让j为升序,dp[i+1]用滚动数组存,因为每次只用到两层dp(和下标的奇偶性),让i降序,即可使每次计算dp[i][j]时,dp[i+1]和dp[i][j-1]均为已知,dp[2][5000]实现dp过程。
Palindrome
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 2084 Accepted Submission(s): 725
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.
5 Ab3bd
2
#include<stdio.h>
#include<string.h>
#define size 5010
int n,dp[2][size];
char a[size];
int min(int a,int b)
{
return a>b?b:a;
}
int main()
{
int i,j,k,l,m;
while(scanf("%d",&n)!=EOF)
{
memset(a,0,sizeof(a));
memset(dp,0,sizeof(dp));
getchar();
scanf("%s",&a);
for(i=n-2;i>=0;i--)
{
for(j=i+1;j<n;j++)
{
if(a[i]==a[j])
dp[i%2][j]=dp[(i+1)%2][j-1];
else
dp[i%2][j]=min(dp[(i+1)%2][j],dp[i%2][j-1])+1;
}
}
printf("%d\n",dp[0][n-1]);
}
return 0;
}贴一个网上的例子
滚动数组很适合用在二维DP而且是数组在很大时,可以节省内存,消除超内存的隐患!具体思想还是看了网上的资料,转载一个,共同享用吧!
滚动数组 举个简单的例子:
int i,d[100];
d[0]=1;d[1]=1;
for(i=2;i<100;i++)
d[i]=d[i-1]+d[i-2];
printf("%d",d[99]);
上面这个循环d[i]只需要解集中的前2个解d[i-1]和d[i-2];
为了节约空间用滚动数组的方法
int d[3];
d[0]=1;d[1]=1;
for(i=2;i<100;i++)
d[i%3]=d[(i-1)%3]+d[(i-2)%3];
printf("%d",d[99%3]);
注意上面的运算,我们只留了最近的3个解,数组好象在“滚动?一样,所以叫滚动数组
对于二维数组也可以用这种方法 例如:
int i,j,d[100][100];
for(i=1;i<100;i++)
for(j=0;j<100;j++)
d[i][j]=d[i-1][j]+d[i][j-1];
上?的d[i][j]忪便赖于d[i-1][j],d[i][j-1];
迿用滚动数组
int i,,j,d[2][100];
for(i=1;i<100;i++)
for(j=0;j<100;j++)
d[i%2][j]=d[(i-1)%2][j]+d[i%2][j-1];
滚动数组实际是一种节约空间的办法,时间上没什么优势,多用于DP中,举个例子先:
一个DP,平常如果需要1000×1000的空间,其实根据DP的特点,能以2×1000的空间解决问题,并且通过滚动,获得和1000×1000一样的效果。
本文介绍了一种使用动态规划方法求解最小补字符数,以将给定字符串转换为回文串的算法。通过滚动数组技术优化内存使用,实现了高效计算。详细解释了算法步骤、关键代码片段及实例应用。
614

被折叠的 条评论
为什么被折叠?



