poj 3280 Cheapest Palindrome(回文字符串dp)

题目链接:http://poj.org/problem?id=3280

 

大致题意:给定一个字符串,字符串中的每个不同的字符都对应一个增加成本和删减成本,问将给定的字符串变成回文字符串所需要的最小成本。

思路:在《挑战程序设计》dp基础练习上看到的这道题,一开始看完题后没有头绪,想不出状态转移方程,后来自己想了一个枚举的方法,就是最后构成的回文串的对称中心一定是原串中的某个字符或者是某两个相邻字符的中间,敲了一个,仔细发现其中有些问题没法处理。 之后就去网上看了题解,自己又敲了一个,A掉了。 主要是注意一下几点:

 

               1.删除和增加在本质上相同的,所以在记录成本是,只要取其中最小的即可。

           2.状态转移方程: c[i]是原串,cost[i]表示花费成本,dp[i][j]表示子列i~j构成回文 的最小花费

           3.最后在更新dp数组的时候一定要注意顺序,使子状态都是已经更新过的状态!!

code:

//poj 3280
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <queue>
#include <stack>
#include <vector>
#include <assert.h>
using namespace std;
#define SIZE 2005
#define INF 100000000

int dp[SIZE][SIZE];
int cost[27];
char c[SIZE];
int M,N;
int Min(int a,int b)
{
    return a<b? a:b;
}
int solve()
{
    memset(dp,0,sizeof(dp));
    for(int j=1;j<M;j++){
        for(int i=j-1;i>=0;i--){
            if(c[i]==c[j]) dp[i][j]=dp[i+1][j-1];
            else dp[i][j]=Min(dp[i+1][j]+cost[c[i]],dp[i][j-1]+cost[c[j]]);
        }
    }
    return dp[0][M-1];
}
int main()
{
    while((scanf("%d%d",&N,&M))!=EOF){
        scanf("%s",c);
        getchar();
        char mid;
        int a,b;
        for(int i=0;i<N;i++){
            scanf("%c %d %d",&mid,&a,&b);
            getchar();
            cost[mid]=Min(a,b);
        }
        printf("%d\n",solve());
    }
    return 0;
}

最后加一点看题解博客时看到的dp小总结,摘过来分享一下:

其实dp很难逃出3种思路:

1、一维线性dp:每次考虑i时,选择最优子问题要么在i-1,要么在1...i-1里;

2、二维线性dp:考虑(i,j)子问题时,选择最优子问题要么在(i+1,j)、(i,j-1),要么在i<= k <=j,在k里;

3、树形dp:考虑i节点最优时,选择子节点最优,一般融合了01背包dp的双重dp。

 

最后各位acmer加油,自己加油!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值