原题地址:http://poj.org/problem?id=3280
题意:题对一个字符串进行插入删除等操作使其变成一个回文串,但是对于每个字符的操作消耗是不同的。求最小消耗。
思路:我们定义为区间 到变成回文的最小代价。
那么对于有三种情况
首先:对于一个串如果,那么
其次:如果是回文串,那么;
最后,如果是回文串,那么;
#include <cmath>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
#include <stack>
#include <set>
#include <map>
#include <cctype>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 1e5 + 5;
const int mod = 998244353;
int n, m;
char s[maxn];
int cost[maxn];
int dp[3005][3005];
int main() {
scanf("%d%d", &m, &n);
scanf("%s", s + 1);
CLR(cost, 0x3f);
for (int i = 1; i <= m; i++) {
char op[2];
int x, y;
scanf("%s %d %d", op, &x, &y);
cost[op[0] - 'a'] = min(x, y);
}
CLR(dp, 0);
//这是另外一种写法,需要初始dp为0x3f
// for (int i = 1; i <= n; i++) {
// dp[i][i] = 0;
// }
// for (int j = 2; j <= n; j++) {
// for (int i = 1; i <= n - j + 1; i++) {
// if (j != 2) {
// if (s[i] == s[i + j - 1]) dp[i][i + j - 1] = dp[i + 1][i + j - 2];
// else {
// dp[i][i + j - 1] = min(dp[i][i + j - 1], dp[i + 1][i + j - 1] + cost[s[i] - 'a']);
// dp[i][i + j - 1] = min(dp[i][i + j - 1], dp[i][i + j - 2] + cost[s[i + j - 1] - 'a']);
// }
// } else {
// if(s[i]==s[i+1])dp[i][i+1]=0;
// dp[i][i + j - 1] = min(dp[i][i + j - 1], dp[i + 1][i + j - 1] + cost[s[i] - 'a']);
// dp[i][i + j - 1] = min(dp[i][i + j - 1], dp[i][i + j - 2] + cost[s[i + j - 1] - 'a']);
// }
// }
// }
for (int i = n; i >= 1; i--) {
for (int j = i + 1; j <= n; 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[1][n]);
return 0;
}