您的位置:首页 > 其它

POJ_3280 Cheapest Palindrome(DP)

2015-09-04 17:32 417 查看
题目请点我

题解:

题目的意思是有一个长度为M的字符串,一共包含N个字母,可以在字符串基础上添加或删除字母,使字符串是一个回文串。

题目看起来比较复杂,字符串可增可减,增减的位置还不确定。参考了别人的博客后发现其实增减的效果是一样的,只需要挑最优的一种方法就好了。减去一个字母,效果相当于在一个对应位置加上该字母。

长度为1的本身就是回文串,随着字符串长度不断增加,我们可以选择在字符串两边添加对应字母,所以按照区间dp,遍历区间长度。

dp定义:dp[i][j],长度从i到j的字符串转换为回文串需要的最小代价。

递推关系式:

0.s[i]=s[j]

dp[i][j] = dp[i+1][j-1];

1.s[i]!=s[j]

dp[i][j] = min(左边加s[i],右边加s[j])

参考博客

代码实现:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>

using namespace std;

const int MAX_N = 30;
const int MAX_M = 2010;
const int INF = 0x7ffffff;

int N,M;
int add[MAX_N];
char str[MAX_M];
int  dp[MAX_M][MAX_M];
int main()
{
scanf("%d%d",&N,&M);
scanf("%s",str);
for( int i = 0; i < N; i++ ){
int a,b;
char tmp;
getchar();
scanf("%c%d%d",&tmp,&a,&b);
add[tmp-'a'] = min(a,b);
}
memset(dp,0,sizeof(dp));
for( int k = 1; k <= M-1; k++ ){
for( int i=0,j=k; j < M; i++,j++ ){
dp[i][j] = INF;
if( str[i] == str[j] ){
dp[i][j] = dp[i+1][j-1];
}
else{
int left = str[i]-'a';
int right = str[j]-'a';
dp[i][j] = min(dp[i][j],min(dp[i+1][j]+add[left],dp[i][j-1]+add[right]));
}
}
}
printf("%d\n",dp[0][M-1]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp