【链接】 我是链接,点我呀:)
【题意】
【题解】
设dp[i][j]表示前i个字符,已经和"hard"匹配前j个的最小花费。 对于dp[i][j] 对s[i+1]分类讨论 ①s[i+1]不删 那么有两种情况 第一种:s[i+1]和"hard"的第j+1个字符匹配 第二种:..xxxxx不匹配 则分别转移到dp[i+1][j+1]和dp[i+1][j] ②s[i+1]删掉 转移到dp[I+1][j]且用dp[i][j]+a[i+1]尝试转移。【代码】
import java.io.*;
import java.util.*;
public class Main {
static InputReader in;
static PrintWriter out;
public static void main(String[] args) throws IOException{
//InputStream ins = new FileInputStream("E:\rush.txt");
InputStream ins = System.in;
in = new InputReader(ins);
out = new PrintWriter(System.out);
//code start from here
new Task().solve(in, out);
out.close();
}
static int N = (int)1e5;
static class Task{
int n;
String s;
long a[] = new long[N+10];
String goal=new String(" hard");
long dp[][] = new long[N+10][10];
public void solve(InputReader in,PrintWriter out) {
n = in.nextInt();
s = in.next();
s = " "+s;
for (int i = 1;i <=n;i++) a[i] = in.nextLong();
for (int i = 0;i <= N;i++)
for (int j = 0;j <= 8;j++)
dp[i][j] = (long)(1e17);
dp[0][0] = 0;
for(int i = 0;i < n;i++)
for (int j = 0;j <= 3;j++) {
//第i+1个不删
if (s.charAt(i+1)==goal.charAt(j+1)) {
dp[i+1][j+1] = Math.min(dp[i+1][j+1], dp[i][j]);
}else {
dp[i+1][j] = Math.min(dp[i+1][j], dp[i][j]);
}
//第i+1个删掉
dp[i+1][j] = Math.min(dp[i+1][j], dp[i][j]+a[i+1]);
}
long ans = dp[n][0];
for (int i = 1;i <= 3;i++) {
ans = Math.min(ans, dp[n][i]);
}
out.println(ans);
}
}
static class InputReader{
public BufferedReader br;
public StringTokenizer tokenizer;
public InputReader(InputStream ins) {
br = new BufferedReader(new InputStreamReader(ins));
tokenizer = null;
}
public String next(){
while (tokenizer==null || !tokenizer.hasMoreTokens()) {
try {
tokenizer = new StringTokenizer(br.readLine());
}catch(IOException e) {
throw new RuntimeException(e);
}
}
return tokenizer.nextToken();
}
public int nextInt() {
return Integer.parseInt(next());
}
public long nextLong() {
return Long.parseLong(next());
}
}
}