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


posted @ 2017-05-08 18:10  yfceshi  阅读(97)  评论(0编辑  收藏  举报