http://poj.org/problem?id=3280

对字符串进行增删操作使其形成回文串,每次操作都有其对应的花费,求最小花费。

典型DP,dp[i][j]为使str[j, i]形成回文的最小花费。

若str[j]==str[i],则dp[i][j]由dp[i-1][j+1]而来。

若str[j]!=str[i],则dp[i][j]=min(dp[i-1][j]+v[data[i]], dp[i][j+1]+v[data[j]]) ;v[data[j]]为增减字符j所花费最小值,因为增加一个字符和减少一个字符起到的效果是相同的,所以预处理出数组v即可。

练习赛时就是没想到预处理这一点而没敢去做。

code:

#include<iostream>//增加和删除的效果一样
#include<cstdio>
#include<cstring>
using namespace std ;
int dp[2001][2001] ;
int v[30], vt[30] ;
int data[2001] ;
char c[2001] ;
int min(int a, int b){
    return a<b ? a:b ;
}
int main(){
    int i, j, n, m ;
    char d ;
    scanf("%d%d", &n, &m) ;
    scanf("%s", c) ;
    for(i=0; i<m; i++)
        data[i] = c[i] - 'a' ;
    for(i=0; i<n; i++){
        scanf("%s", c) ;
        scanf("%d%d", &v[c[0]-'a'], &vt[c[0]-'a']) ;
        v[c[0]-'a'] = min(v[c[0]-'a'], vt[c[0]-'a']) ;
    }
    for(i=1; i<m; i++){
        for(j=i-1; j>=0; j--){
            if(data[i]==data[j])
                dp[i][j] = dp[i-1][j+1] ;
            else
                dp[i][j] = min(dp[i-1][j]+v[data[i]], dp[i][j+1]+v[data[j]]) ;
        }
    }
    printf("%d\n", dp[m-1][0]) ;
    return 0 ;} 
posted on 2012-04-14 21:45  追逐.  阅读(206)  评论(0编辑  收藏  举报