poj 3280 区间dp
题意:给你m个字符。当中有n种字符,每种字符都有两个值,各自是添加一个这种字符的代价。删除一个这种字符的代价,让你求将原先给出的那串字符变成回文串的最小代价。
思路:区间dp 设dp[i][j]表示从i到j区间满足条件的最优解
状态方程:
if(str[i]==str[j])dp[i][j]=dp[i+1][j-1];
else
dp[i][j]=min(dp[i+1][j]+val[str[i]-'a'],dp[i][j-1]+val[str[j]-'a']);
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#define N 10005<<1
#define INF 10000000
#define LL long long
#define eps 10E-9
#define mem(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define w(a) while(a)
#define s(a) scanf("%d",&a)
#define ss(a,b) scanf("%d%d",&a,&b)
#define sss(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define PI acos(-1.0)
using namespace std;
int dp[2002][2002];
int val[27];
int main(){
int n, m, a, b;
string str;
char c;
w(~ss(n,m)){
mem(dp);
cin>>str;
str += '0';
for(int i=0; i<n; i++){
cin>>c>>a>>b;
val[c-'a'] = min(a, b);
}
for(int i=m-1; i>=0; i--){
for(int j=i+1; j<m; j++){
if(str[i] == str[j]) dp[i][j] = dp[i+1][j-1];
else dp[i][j] = min(dp[i+1][j] + val[str[i] - 'a'], dp[i][j-1] + val[str[j] - 'a']);
}
}
cout<<dp[0][m-1]<<endl;
}
return 0;
}