POJ 3280:Cheapest Palindrome 区间DP好题

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;
}

 
原文地址:https://www.cnblogs.com/kiuhghcsc/p/5748360.html