poj3280 Cheapest Palindrome(动态规划)

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

题目大意:有一个字符串由N(1<=N<=26)种小写字母组成,长度为M(1<=M<=2000),

在字符串中任意位置添加或删除字母使字符串变成一个回文串,添加和删除有一定的花费。求这个最小花费。

动态规划策略:设dp[i][j]为字符串从 i 到 j 成为回文串的最小花费。

dp[i][j]可能由三种状态转移过来:

在头部添加一个:dp[i+1][j]+cost[i]

在尾部添加一个:dp[i][j-1]+cost[j]

不添加:dp[i+1][j-1]  if ( str[i] == str[j] )

使用双层循环遍历 所有的(i,j),复杂度为O(M^2)。

Sample Input

3 4
abcb
a 1000 1100
b 350 700
c 200 800

Sample Output

900

Hint

If we insert an "a" on the end to get "abcba", the cost would be 1000. If we delete the "a" on the beginning to get "bcb", the cost would be 1100. If we insert "bcb" at the begining of the string, the cost would be 350 + 200 + 350 = 900, which is the minimum.

 

下面是已AC的代码:

#include <iostream>  
#include <cstdio>  
#include <string>  

using namespace std;  

string str;  
struct ST{  
	char ch;  
	int add, del;  
} st[30];  
int chp[30];  
int dp[2010][2010]; // dp[i][j]:字符串从i到j为回文串的代价  

int main()  
{  
	int N, M;  
	cin >> N >> M;  
	cin >> str;  
	for ( int i = 0 ; i < N ; ++ i ) {  
		cin >> st[i].ch >> st[i].add >> st[i].del;  
		chp[st[i].ch-'a'] = min(st[i].add, st[i].del);  
	}  
	for ( int i = 1 ; i < M ; ++ i ) {  
		for ( int j = i-1 ; j >= 0 ; -- j ) {  
			// 头部变化 或尾部变化  
			dp[j][i] = min(dp[j+1][i]+chp[str[j]-'a'], dp[j][i-1]+chp[str[i]-'a']);
			// 如果相等则可能没有变动字符   
			if ( str[i] == str[j] ) dp[j][i] = min(dp[j][i], dp[j+1][i-1]);
		}  
	}  
	
	cout << dp[0][M-1] << endl;  
	return 0;  
}  

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值