Cheapest Palindrome
题目链接:
http://poj.org/problem?id=3280
题意:
给出一个只由小写字母组成的串,可以添加或删除一些字母(添加和删除都需要花费且花费不同),求将这个串改变成一个回文串的最小花费。
题解:
设dp[i][j]是将区间[i,j]改变成回文串的最小花费,则两种情况
①显而易见,当s[i]==s[j]时,dp[i][j]=dp[i+1][j-1]
②当s[i]!=s[j]时,dp[i][j]有四种可能的取值,区间 [i,j-1] 删除s[i]、在s[j-1]的右侧添加s[i]、区间 [i+1,j] 删除s[j]、在s[i+1]的左侧添加s[j],则此时dp[i][j]=min(dp[i][j-1]+del[i],dp[i][j-1]+add[i],dp[i+1][j]+del[j],dp[i+1][j]+add[j]);
代码
#include<stdio.h>
#include<string.h>
const int N=2001;
int dp[N][N],cost1[26],cost2[26];
char s[N],a[2];
int mmin(int x,int y)
{
return x<y?x:y;
}
void solve()
{
int n,m,b,c;
memset(dp,0,sizeof(dp));
while(~scanf("%d%d",&n,&m))
{
scanf("%s",s+1);
for(int i=1;i<=n;++i)
{
scanf("%s%d%d",a,&b,&c);
cost1[a[0]-'a']=b;
cost2[a[0]-'a']=c;
}
for(int len=1;len<m;++len)
{
for(int i=1;i+len<=m;++i)
{
int j=i+len;
if(s[i]==s[j])dp[i][j]=dp[i+1][j-1];
else
{
b=dp[i+1][j]+mmin(cost1[s[i]-'a'],cost2[s[i]-'a']);
c=dp[i][j-1]+mmin(cost1[s[j]-'a'],cost2[s[j]-'a']);
dp[i][j]=mmin(b,c);
}
}
}
printf("%d
",dp[1][m]);
}
}
int main()
{
solve();
return 0;
}