Cheapest Palindrome
直接翻译了
Descriptions
给定一个字符串S,字符串S的长度为M(M≤2000),字符串S所含有的字符的种类的数量为N(N≤26),然后给定这N种字符Add与Delete的代价,求将S变为回文串的最小代价和。
Input
第一行:两个由空格分隔的整数 N 和 M
第二行:这一行给出了恰好 M 个字符,表示初始状态下的ID字符串
接下来的 N 行:每一行给出了由空格分隔的三部分。首先是一个字符,保证出现在了输入的字符串中。接下来是两个整数,表示你增添这个字符的代价,然后是删除这个字符的代价
Output
你只需要输出一行,且只输出一个整数。表示你将给定字符串变成回文串所需的最小代价。
Sample Input
3 4 abcb a 1000 1100 b 350 700 c 200 800
Sample Output
900
题目链接
https://vjudge.net/problem/POJ-3280
首先要先知道删除一个字母和添加一个字母没有区别,那么这个字母的价值就是value[c]=min(Add,Delete)
用dp[i][j]表示字符串中第i个字符到第j个字符为回文时,所花费的最小代价。dp[i][j]可以由dp[i+1][j]或者dp[i][j-1]转移而来。例:bcb可以由bc或cb转移而来
如果第i个字符和第j个字符相同,那么不需要添加其余的操作和代价,dp[i][j] = dp[i+1][j-1]。
如果第i个字符和第j个字符不同,那么dp[i][j]=dp[i+1][j]删除第i个字符,或者再最右侧添加第i个字符;也可以由dp[i][j-1]删除第j个字符,或者再最左侧添加第j个字符。
总之要选择第i个字符或第j个字符中删除或者添加代价最小的一种操作进行。
AC代码
#include <iostream> #include <cstdio> #include <fstream> #include <algorithm> #include <cmath> #include <deque> #include <vector> #include <queue> #include <string> #include <cstring> #include <map> #include <stack> #include <set> #include <sstream> #define IOS ios_base::sync_with_stdio(0); cin.tie(0); #define Mod 1000000007 #define eps 1e-6 #define ll long long #define INF 0x3f3f3f3f #define MEM(x,y) memset(x,y,sizeof(x)) #define Maxn 2005 using namespace std; int N,M; string s; int dp[Maxn][Maxn]; int value[Maxn];//字母的价值 int main() { cin>>N>>M; cin>>s; for(int i=0; i<N; i++) { char c; int x,y; cin>>c>>x>>y; value[c]=min(x,y);//获取最小价值 } MEM(dp,0); for(int j=1; j<M; j++) { for(int i=j-1; i>=0; i--) { if(s[i]==s[j])//相等 dp[i][j]=dp[i+1][j-1]; else//不等 dp[i][j]=min(dp[i][j-1]+value[s[j]],dp[i+1][j]+value[s[i]]); } } cout<<dp[0][M-1]<<endl; return 0; }