POJ 3280 Cheapest Palindrome (dp)

原题地址:http://poj.org/problem?id=3280

题意:题对一个字符串进行插入删除等操作使其变成一个回文串,但是对于每个字符的操作消耗是不同的。求最小消耗。

思路:我们定义dp [ i ] [ j ]为区间ij变成回文的最小代价。
那么对于dp[i][j]有三种情况
首先:对于一个串如果s[i]==s[j],那么dp[i][[j=dp[i+1][j-1]
其次:如果dp[i+1][j]是回文串,那么dp[i][j]=dp[i+1][j]+min(add[i],del[i])
最后,如果dp[i][j-1]是回文串,那么dp[i][j]=dp[i][j-1] + min(add[j],del[j])

#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;
}

猜你喜欢

转载自blog.csdn.net/yiqzq/article/details/81675239