POJ-1159-Palindrome -dp

给一个长度为 5000的串

找出 最少插入多少个字符 得到一个回文串

思路1:

把该串和其逆序 求一遍 LCS.  答案就是len-lcs


思路2:

dp   

 

	if (tm[i]==tm[j])
				dp[i][j]=dp[(i+1)][j-1];
			else
				dp[i][j]=min(dp[(i+1)][j],dp[i][j-1])+1;   

可用dfs或者for循环

由于内存太大,用dfs不好用上滚动数组。。。



dfs版本

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;
int min(int a,int b) 
{return a<b?a:b;}
int min(int a,int b,int c)
{ 
return min(c,min(a,b));}
char tm[5005];
int dp[5005][5005];
const int inf=1147483647;
int dfs(int i,int j)
{
	if (i>j)
		return 0;
	if (i==j) 
	return 	dp[i][j]=0;

	if (dp[i][j])  
		return dp[i][j];
 
	if (tm[i]!=tm[j])
	return dp[i][j]=min(dfs(i+1,j),dfs(i,j-1))+1;
	else 
		return dp[i][j]= dfs(i+1,j-1);
	 
}


int main()
{
int n;
 cin>>n;
scanf("%s",tm);
int len=n; 

 dfs(0,n-1);
printf("%d\n",dp[0][n-1]);
	return 0;
 
}


滚动数组版本

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;
int min(int a,int b) 
{return a<b?a:b;}
int min(int a,int b,int c)
{ 
	return min(c,min(a,b));
}
char tm[5005];
short dp[2][5005];  
int main()
{
	int n;
	cin>>n;
	scanf("%s",tm);
	int len=n; 
	int i,j; 
	
	for (i=n-1;i>=0 ;i--)
	{
		
		for (j=i+1;j<n;j++)
		{
			if (tm[i]==tm[j])
				dp[i&1][j]=dp[(i+1)&1][j-1];
			else
				dp[i&1][j]=min(dp[(i+1)&1][j],dp[i&1][j-1])+1;  //因为推dp[i][j]需要(后面)i+1的情况和(前面)j-1的情况,所以决定了2个循环的方向不同
			
		}
	}
	
	printf("%d\n",dp[0][n-1]);
	return 0;
	
}



你可能感兴趣的:(POJ-1159-Palindrome -dp)