给你一个字符串,把它变成回文串,可以添加字母也可以删除其中的字母,对于每一个字母添加和删除需要不同的花费,问使得这个字符串变成回文串最少需要花多少
区间DP,从后向前推,如果区间[i,j] s[i] == s[j],那么dp[i][j] = dp[i+1][j-1], 如果不想等 那么要么是加上一个 或者删除一个,在这里举个例子把,当推到abcb的时候,操作无非两种 删除a或者加上一个a,这两个操作其实是一样的只不过花费不一样,所以可以直接取添加删除中花费较小的那个即可,这样就不用太多的状态转移方程了,一开始添加删除分开写的 有点繁琐,写到一半觉得是一样的
#include<iostream> #include<cstdio> #include<list> #include<algorithm> #include<cstring> #include<string> #include<queue> #include<stack> #include<map> #include<vector> #include<cmath> #include<memory.h> #include<set> #define ll long long #define eps 1e-8 #define inf 0xfffffff //const ll INF = 1ll<<61; using namespace std; //vector<pair<int,int> > G; //typedef pair<int,int > P; //vector<pair<int,int> > ::iterator iter; // //map<ll,int >mp; //map<ll,int >::iterator p; //#define IN freopen("c:\\Users\\linzuojun\\desktop\\input.txt", "r", stdin) //#define OUT freopen("c:\\Users\\linzuojun\\desktop\\output.txt", "w", stdout) int dp[3000 + 5][3000 + 5]; int cost[1000 + 5]; string s; typedef struct Node { string str; int get,lose; }; Node node[10000 + 5]; void clear() { memset(dp,0,sizeof(dp)); memset(node,0,sizeof(node)); memset(cost,0,sizeof(cost)); } int main() { int n,m; while(cin>>n>>m) { clear(); cin>>s; for(int i=0;i<n;i++) { cin>>node[i].str>>node[i].get>>node[i].lose; cost[node[i].str[0] - ‘a‘] = min(node[i].get,node[i].lose); } for(int i=m-1;i>=0;i--) { for(int j=i+1;j<m;j++) { if(s[i] == s[j]) dp[i][j] = dp[i+1][j-1];//两头的相等就不需要处理了 else dp[i][j] = min(dp[i+1][j] + cost[s[i]-‘a‘],dp[i][j-1] + cost[s[j]-‘a‘]);//两头不等,是加一个相同的或者取出一个比较大小 } } printf("%d\n",dp[0][m-1]); } return EXIT_SUCCESS; }
POJ3280 Cheapest Palindrome 区间DP,布布扣,bubuko.com
POJ3280 Cheapest Palindrome 区间DP
原文:http://blog.csdn.net/yitiaodacaidog/article/details/19937313