跟踪所有奶牛可能是一项棘手的任务,所以农夫约翰安装了一个系统来自动化这个过程。他在每头奶牛身上安装了一个电子ID标签,系统会在奶牛经过扫描仪时读取它们。每个ID标签的内容目前是一个长度为 M(1 ≤ M ≤ 2,000)的字符串,由 N(1 ≤ N ≤ 26)个不同符号(即小写罗马字母表)组成。
奶牛是调皮的生物,有时会试图欺骗系统,倒着走。虽然一个ID为 "abcba" 的奶牛无论向哪个方向走都会读取相同的内容,但一个ID为 "abcb" 的奶牛可能会注册为两个不同的ID("abcb" 和 "bcba")。
约翰希望更改奶牛的ID标签,使其无论奶牛向哪个方向走都能读取相同的内容。例如,"abcb" 可以通过在末尾添加 "a" 来变为 "abcba",使得ID是回文的(正向和反向读取内容相同)。将ID更改为回文的其他方法包括在开头添加三个字母 "bcb" 以得到ID "bcbabcb",或者删除字母 "a" 以得到ID "bcb"。可以在字符串的任何位置添加或删除字符,得到比原始字符串长或短的字符串。
不幸的是,由于ID标签是电子的,每个字符的插入或删除都有一个成本(0 ≤ cost ≤ 10,000),具体取决于要添加或删除的字符值。给定奶牛的ID标签内容和插入或删除每个字母的成本,找出更改ID标签以满足约翰要求的最小成本。将空ID标签视为满足正向和反向读取相同内容的要求。只能添加带有关联成本的字母到字符串中。
输入
Line 1: 两个用空格分隔的整数: N 和 M
Line 2: 此行包含恰好 M 个字符,构成初始ID字符串
Lines 3..N+2: 每行包含三个用空格分隔的实体: 输入字母表中的一个字符和两个整数,分别是添加和删除该字符的成本。
输出
Line 1: 一行,一个整数,表示更改给定名称标签的最小成本。
示例
Inputcopy | Outputcopy |
---|---|
3 4 abcb a 1000 1100 b 350 700 c 200 800 | 900 |
提示
如果我们在末尾插入一个 "a" 得到 "abcba",成本将为 1000。如果我们删除开头的 "a" 得到 "bcb",成本将为 1100。如果我们在字符串开头插入 "bcb",成本将为 350 + 200 + 350 = 900,这是最小成本。
题意:给你一串字符,给出每个字符删除以及添加的代价,求让这个字符串变成回文串的最小代价。
考虑区间DP,状态表示dp[i][j] 表示区间i ~ j 变成回文串的最小代价,考虑状态转移,对于字符i
可以是i+1 ~ j的右边加上s [ j ] 形成回文串,也可以是删除s[i]形成回文串,对于 j 同理,当然要特殊情况s[ i ] = s[ j ],此时dp[ i ][ j ] = dp[ i + 1 ][ j - 1 ];最后写出状态转移方程即可:
d表示删除该字母的代价,a表示增加
代码如下:
#include <stdio.h>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <string>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <ctime>
#include <vector>
#include <fstream>
#include <list>
#include <iomanip>
#include <numeric>
using namespace std;
#define endl '\n'
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
map<char,int>ma,md;
int min(int x,int y)
{
if(x > y) return y;
return x;
}
int dp[2010][2010];
void solve()
{
int m,n;
cin >> m >> n;
string s;
cin >> s;
s = ' ' + s;
while(m--)
{
char x;
int a,b;
cin >> x >> a >> b;
ma[x] = a;
md[x] = b;
}
memset(dp,0x3f,sizeof(dp));
for(int i = 1;i <= n;i++)
{
dp[i][i] = 0;
}
for(int len = 2;len <= n;len++)
{
for(int i = 1;i + len - 1 <= n;i++)
{
int j = i + len - 1;
dp[i][j] = min(dp[i][j],dp[i+1][j] + min(ma[s[i]],md[s[i]]));
dp[i][j] = min(dp[i][j],dp[i][j - 1] + min(ma[s[j]],md[s[j]]));
if(s[i] == s[j])
{
if(j == i+1) dp[i][j] = 0;
else dp[i][j] = min(dp[i][j],dp[i+1][j-1]);
}
}
}
cout << dp[1][n] << endl;
return;
}
signed main()
{
ios::sync_with_stdio(false),cin.tie(0);
int tt;
tt = 1;
while(tt--)
{
solve();
}
return 0;
}