题目链接:
POJ-3280
大意:
给一个串,给出每个字母删去和增加的代价(cost) 要求使之变成回文串的最小代价
分析:
考虑区间 DP 方程, dp(i,j) 表示从 i 到 j 的最小代价,那么 i 到 j 已经考虑完回文了
对于 dp(i,j) 方向有 dp(i+1,j) 和 dp(i,j-1) 两个,分别从增加和删除两种方式中取小值
dp方程:
if s[i] == s[j]
dp[i][j]=dp[i+1][j-1];
else
dp[i][j]=
min{
dp[i+1][j]+min(a[s[i]],d[s[i]]);
dp[i][j-1]+min(a[s[j]],d[s[j]]);
}
具体实现:
#include<iostream>
#include<string>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<map>
#include<cmath>
using namespace std;
typedef long long ll;
typedef pair <int, int> pii;
#define mem(s,t) memset(s,t,sizeof(s))
#define D(v) cout<<#v<<" "<<v<<endl
#define inf 0x3f3f3f3f
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#pragma warning(disable:4996)
#pragma comment(linker, "/STACK:336777216")
//#define LOCAL
const int mod = 1e9 + 7;
const int MAXN = 2e3 + 10;
int n,m;
string s,ss;
map<char,int> a,d;
int dp[MAXN][MAXN];
int main() {
mem(dp,0);
cin>>m>>n;
cin>>s;
for(int i=0;i<m;i++){
cin>>ss;
cin>>a[ss[0]]>>d[ss[0]];
}
for(int len=1;len<=n;len++){
for(int i=0;i+len<n;i++){
int j=i+len;
if(s[i]==s[j]){
dp[i][j]=dp[i+1][j-1];
}
else {
int ans1=dp[i+1][j]+min(a[s[i]],d[s[i]]);
int ans2=dp[i][j-1]+min(a[s[j]],d[s[j]]);
dp[i][j]=min(ans1,ans2);
}
}
}
cout<<dp[0][n-1]<<endl;
return 0;
}