您的位置:首页 > 其它

poj 3280 Cheapest Palindrome

2016-08-02 16:53 381 查看
链接:http://poj.org/problem?id=3280

思路:题目给出n种m个字符,每个字符都有对应的添加和删除的代价,求出构成最小回文串的代价

dp[i][j]代表区间i到区间j成为回文串的最小代价,那么对于dp[i][j]有三种情况:

1、dp[i+1][j]表示区间i+1到区间j已经是回文串了的最小代价,那么对于s[i]这个字母,我们有两种操作,删除与添加,对应有两种代价,dp[i+1][j]+add[s[i]],dp[i+1][j]+del[s[i]],取这两种代价的最小值;

2、dp[i][j-1]表示区间i到区间j-1已经是回文串了的最小代价,那么对于s[j]这个字母,同样有两种操作,dp[i][j-1]+add[s[j]],dp[i][j-1]+del[s[j]],取最小值

3、若是s[i]==s[j],dp[i+1][j-1]表示区间i+1到区间j-1已经是回文串的最小代价,那么对于这种情况,我们考虑dp[i][j]与dp[i+1][j-1]的大小

然后dp[i][j]取上面这些情况的最小值

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<vector>
#include<queue>
#include<iterator>
#include<vector>
#include<set>
#define dinf 0x3f3f3f3f
typedef long long ll;

using namespace std;

char s[2005],c[5];
int dp[2005][2005],add[2005],del[2005];

int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(dp,0,sizeof(dp));
scanf("%s",s+1);
s[0]=2;

for(int i=1;i<=n;i++)
{
char ch[10];
int tmp1,tmp2;
scanf("%s%d%d",ch,&tmp1,&tmp2);
add[ch[0]-'a'+1]=tmp1;
del[ch[0]-'a'+1]=tmp2;
}
for(int i=m-1;i>=1;i--)
for(int j=i+1;j<=m;j++)
{
dp[i][j]=min(dp[i+1][j]+add[s[i]-'a'+1],dp[i+1][j]+del[s[i]-'a'+1]);
int tmp=min(dp[i][j-1]+add[s[j]-'a'+1],dp[i][j-1]+del[s[j]-'a'+1]);
dp[i][j]=min(dp[i][j],tmp);
if(s[i]==s[j])
dp[i][j]=min(dp[i][j],dp[i+1][j-1]);
}
printf("%d\n",dp[1][m]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: