题意
传送门 POJ 3280
考虑已知较小区间处理为回文的最小花费,此时递推式
d p [ l ] [ r ] = m i n ( d p [ l + 1 ] [ r ] + c o s t [ l ] , d p [ l ] [ r − 1 ] + c o s t [ r ] ) dp[l][r] = min(dp[l+1][r]+cost[l],dp[l][r-1]+cost[r]) dp[l][r]=min(dp[l+1][r]+cost[l],dp[l][r−1]+cost[r])
考虑不删增元素 [ l , r ] [l, r] [l,r] 也为回文的情况
d p [ l ] [ r ] = m i n ( d p [ l ] [ r ] , d p [ l + 1 ] [ r − 1 ] ) dp[l][r]=min(dp[l][r],dp[l+1][r-1]) dp[l][r]=min(dp[l][r],dp[l+1][r−1])
实现上采用记忆化搜索。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#define min(a,b) (((a) < (b)) ? (a) : (b))
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define abs(x) ((x) < 0 ? -(x) : (x))
#define INF 0x3f3f3f3f
#define delta 0.85
#define eps 1e-3
#define PI 3.14159265358979323846
#define MAX_M 2020
using namespace std;
int N, M;
int cost[26];
char name[MAX_M];
int dp[MAX_M][MAX_M];
int rec(int l, int r){
if(l >= r) return 0;
if(dp[l][r] != -1) return dp[l][r];
int res = name[l] == name[r] ? rec(l + 1, r - 1) : INF;
res = min(res, min(rec(l + 1, r) + cost[name[l] - 'a'], rec(l, r - 1) + cost[name[r] - 'a']));
return dp[l][r] = res;
}
int main(){
while(~scanf("%d%d", &N, &M)){
memset(dp, -1, sizeof(dp));
scanf("%s", name);
for(int i = 0; i < N; i++){
char c;
int a, b;
scanf(" %c%d%d", &c, &a, &b);
cost[c - 'a'] = min(a, b);
}
printf("%d\n", rec(0, M - 1)); // [0, M - 1]
}
return 0;
}