代码注释清晰,如果还不能理解请参考我的另一篇博客,链接: (详解)区间DP —— 平行四边形优化.,希望对你有所帮助!!!
题目信息:
描述
跟踪所有母牛可能是一项艰巨的任务,因此,农夫约翰(Farmer John)已安装了一个使它自动化的系统。他在每头奶牛上安装了一个电子ID标签,当奶牛经过扫描仪时,系统会读取该电子ID标签。各ID标签的内容目前单个字符串与长度中号(1≤ 中号 ≤2000)从的字母表字符绘制Ñ(1≤ Ñ ≤26)不同的符号(即,小写罗马字母)。
母牛是顽皮的动物,有时试图通过向后走来欺骗该系统。尽管ID为“ abcba”的母牛无论走到哪个方向都将读取相同的信息,但是ID为“ abcb”的母牛可能会注册为两个不同的ID(“ abcb”和“ bcba”)。
FJ希望更改奶牛的ID标签,以便无论奶牛走过的方向如何都可以读取相同的信息。例如,可以通过在末尾添加“ a”以形成“ abcba”来更改“ abcb”,以便ID是回文的(向前和向后读取相同的内容)。将ID更改为回文的其他一些方法包括在开头添加三个字母“ bcb”以产生ID“ bcbabcb”,或删除字母“ a”以产生ID“ bcb”。可以在字符串的任何位置添加或删除字符,从而产生比原始字符串长或短的字符串。
不幸的是,由于ID标签是电子标签,因此每个字符的插入或删除都有一个成本(0≤ 成本 ≤10,000),具体取决于要添加或删除哪个字符值。考虑到母牛ID标签的内容以及插入或删除每个字母字符的成本,请找到更改ID标签以使其满足FJ要求的最低成本。空的ID标签被认为满足向前和向后读取相同ID的要求。只能将带有相关费用的字母添加到字符串中。
输入项
第1行:两个以空格分隔的整数:N和M
第2行:此行恰好包含构成初始ID字符串的M个字符
第3行。N +2:每行包含三个以空格分隔的实体:输入字母的字符和两个整数,分别是添加和删除该字符的成本。
输出
第1行:具有单个整数的一行,这是更改给定名称标签的最低成本。
样本输入
3 4
abcb
a 1000 1100
b 350 700
c200 800
样本输出
900
注意事项:
- 区间DP模版(三要素):
区间长度
区间起点、终点(由长度与起点推出终点、最后一个起点的位置)
AC代码(java):
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int m=sc.nextInt();
String str=sc.nextLine(); //吸收空格
char[] s=sc.nextLine().toCharArray(); //记录字符串
int[][] dp=new int[m+5][m+5]; //状态数组:保存子字符串s(i,j)转化为回文序列的最小花费
int[] cost=new int[30]; //记录某个字母最小花费
for(int i=1;i<=n;i++) {
char c=sc.next().charAt(0);
int x=sc.nextInt();
int y=sc.nextInt();
cost[c-'a']=Math.min(x, y); //记录最小花费(删除还是添加)
}
for(int len=2;len<=m;len++) { //枚举长度
for(int i=m-len;i>=0;i--) {
int j=i+len-1; //通过起点计算终点
if(s[i]==s[j]) { //第一种情况
dp[i][j]=dp[i+1][j-1];
}
else {
dp[i][j]=Math.min(dp[i+1][j]+cost[s[i]-'a'], dp[i][j-1]+cost[s[j]-'a']); //第二种情况,状态转移方程
}
}
}
System.out.println(dp[0][m-1]);
}
}