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\n",dp[1][m]); } } int main() { solve(); return 0; }
时间: 2024-10-10 14:19:31