poj 1159 动态规划

这是一道基本的动态规划题,可惜我连一个正确的dp方法都没想出来。惭愧。

一直认为DP是几种编程思想里最难掌握的,“状态转移式子”很难总结出来。DP真的应该多练一练。

这道题的两个思路:

思路1:设min[i][j]表示字符串str[i~j]转化为对称串所需添加的最小字符数,则

当str[i]==str[j]时,min[i][j]=min[i+1][j-1];

否则,min[i][j]=1+Min(min[i+1][j],min[i][j-1])

思路2:把str转化为对称串所需添加的最小字符数==strlen(str)-strlen(str与它的反序串reverse_str的最长公共子序列)

求最长公共子序列的方法:

设dp[i][j]表示字符串str1[0~i]与字符串str2[0~j]的最长公共子序列,则

当str1[i]==str2[j]时,dp[i][j]=dp[i-1][j-1]+1;

否则,dp[i][j]=Max(dp[i-1][j],dp[i][j-1]);

代码如下:

/*
 * =====================================================================================
 *
 *       Filename:  1159.c
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  2012年05月16日 11时57分38秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  MaZheng (blog.csdn.net/mazheng1989), mazheng19891019@gmail.com
 *        Company:  Dalian University Of Technology
 *
 * =====================================================================================
 */


#include<stdio.h>
#define	Max_Len 5005			/*  */
#define	Min(a,b) ((a)>(b)?(b):(a))			/*  */

//please declare parameters here.
short min[Max_Len][Max_Len];
int N;
char str[Max_Len];
//please declare functions here.
 
int main()
{
	 if(freopen("input.txt","r",stdin)==NULL) perror("Can not open the input file!");
	 
	//input your ...
	scanf("%d\n",&N);
	scanf("%s",str+1);
//	puts(str+1);
	int i,j;
	for(i=N;i>0;i--)
	{
		for(j=1;j<=N;j++)
		{
//			printf("%c %c\n",str[i],str[j]);
			if(i==j)
			{
				continue;
			}
			if(str[i]==str[j])
			{
				min[i][j]=min[i+1][j-1];
			}
			else
			{
				min[i][j]=1+Min(min[i+1][j],min[i][j-1]);
			}
		}
	}
	printf("%d\n",min[1][N]);
	return 0;
}


/*
 * =====================================================================================
 *
 *       Filename:  1159a.c
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  2012年05月16日 12时52分15秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  MaZheng (blog.csdn.net/mazheng1989), mazheng19891019@gmail.com
 *        Company:  Dalian University Of Technology
 *
 * =====================================================================================
 */


#include<stdio.h>
#define	Max(a,b) ((a)>(b)?(a):(b))			/*  */
#define	Max_Len 5005			/*  */
short dp[Max_Len][Max_Len];
int N;
char str1[Max_Len],str2[Max_Len];
//please declare parameters here.


//please declare functions here.

int main()
{
	 if(freopen("input.txt","r",stdin)==NULL) perror("Can not open the input file!");
	 
	//input your ...
	scanf("%d\n",&N);
	scanf("%s",str1+1);
	int i,j;
	for(i=1;str1[i];i++)
	{
		str2[N+1-i]=str1[i];
	}
	for(i=1;i<=N;i++)
	{
		for(j=1;j<=N;j++)
		{
			if(str1[i]==str2[j])
			{
				dp[i][j]=dp[i-1][j-1]+1;
			}
			else
			{
				dp[i][j]=Max(dp[i-1][j],dp[i][j-1]);
			}
		}
	}
	printf("%d\n",N-dp[N][N]);
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值