DP-Easy Problem - CodeForces - 1096D
题意:
给 定 一 个 长 度 为 n 的 字 符 串 s , 可 以 删 除 任 意 位 置 上 的 字 母 , 删 除 第 i 位 的 字 母 需 要 花 费 代 价 a [ i ] 。 要 以 最 小 代 价 使 得 s 中 不 存 在 子 串 “ h a r d ” , 求 最 小 代 价 。 给定一个长度为n的字符串s,可以删除任意位置上的字母,删除第i位的字母需要花费代价a[i]。\\要以最小代价使得s中不存在子串“hard”,求最小代价。 给定一个长度为n的字符串s,可以删除任意位置上的字母,删除第i位的字母需要花费代价a[i]。要以最小代价使得s中不存在子串“hard”,求最小代价。
Input:
6
hhardh
3 2 9 11 7 1
Output:
5
Input:
8
hhzarwde
3 2 6 9 4 8 7 1
Output:
4
Input:
6
hhaarr
1 2 3 4 5 6
Output:
0
数据范围:
n ∈ [ 1 , 100000 ] , a i ∈ [ 1 , 998244353 ] 。 T i m e l i m i t : 2000 m s , M e m o r y l i m i t : 262144 k B n∈[1,100000],a_i∈[1,998244353]。\\Time\ limit:2000 ms,Memory \ limit:262144 kB n∈[1,100000],ai∈[1,998244353]。Time limit:2000ms,Memory limit:262144kB
题解:
字 符 串 中 是 否 存 在 “ h a r d ” 其 实 与 “ h a r ” 是 否 存 在 有 直 接 关 系 , 而 “ h a r ” 是 否 存 在 与 “ h a ” 是 否 存 在 有 关 . . . 设 d p [ i ] [ 1 ] : 使 得 前 i 个 字 符 当 中 不 存 在 “ h ” 所 需 花 费 的 最 小 代 价 。 d p [ i ] [ 2 ] : 使 得 前 i 个 字 符 当 中 不 存 在 “ h a ” 所 需 花 费 的 最 小 代 价 。 d p [ i ] [ 3 ] : 使 得 前 i 个 字 符 当 中 不 存 在 “ h a r ” 所 需 花 费 的 最 小 代 价 。 d p [ i ] [ 4 ] : 使 得 前 i 个 字 符 当 中 不 存 在 “ h a r d ” 所 需 花 费 的 最 小 代 价 。 则 每 种 情 况 与 前 者 的 关 系 : d p [ i ] [ j ] = m i n ( d p [ i − 1 ] [ j − 1 ] , d p [ i − 1 ] [ j ] + a [ i ] ) , 就 是 当 前 字 母 删 除 与 否 的 关 系 。 若 不 删 除 第 i 个 字 母 , 那 么 前 i − 1 个 字 母 当 中 不 存 在 第 i 个 字 母 的 前 缀 。 若 删 除 第 i 个 字 母 , 则 当 前 代 价 为 相 同 情 况 下 前 i − 1 个 字 母 的 代 价 , 再 加 上 a [ i ] 。 字符串中是否存在“hard”其实与“har”是否存在有直接关系,而“har”是否存在与“ha”是否存在有关...\\\ \\设dp[i][1]:使得前i个字符当中不存在“h”所需花费的最小代价。\\\quad dp[i][2]:使得前i个字符当中不存在“ha”所需花费的最小代价。\\\quad dp[i][3]:使得前i个字符当中不存在“har”所需花费的最小代价。\\\quad dp[i][4]:使得前i个字符当中不存在“hard”所需花费的最小代价。\\\ \\则每种情况与前者的关系:dp[i][j]=min(dp[i-1][j-1],dp[i-1][j]+a[i]),就是当前字母删除与否的关系。\\\ \\若不删除第i个字母,那么前i-1个字母当中不存在第i个字母的前缀。\\若删除第i个字母,则当前代价为相同情况下前i-1个字母的代价,再加上a[i]。 字符串中是否存在“hard”其实与“har”是否存在有直接关系,而“har”是否存在与“ha”是否存在有关... 设dp[i][1]:使得前i个字符当中不存在“h”所需花费的最小代价。dp[i][2]:使得前i个字符当中不存在“ha”所需花费的最小代价。dp[i][3]:使得前i个字符当中不存在“har”所需花费的最小代价。dp[i][4]:使得前i个字符当中不存在“hard”所需花费的最小代价。 则每种情况与前者的关系:dp[i][j]=min(dp[i−1][j−1],dp[i−1][j]+a[i]),就是当前字母删除与否的关系。 若不删除第i个字母,那么前i−1个字母当中不存在第i个字母的前缀。若删除第i个字母,则当前代价为相同情况下前i−1个字母的代价,再加上a[i]。
注意:
①
、
边
界
的
处
,
j
=
0
的
情
况
赋
值
为
i
n
f
。
②
、
更
新
要
及
时
。
③
、
根
据
a
i
的
范
围
,
i
n
f
需
要
大
于
1
0
10
①、边界的处,j=0的情况赋值为inf。\\②、更新要及时。\\③、根据a_i的范围,inf需要大于10^{10}
①、边界的处,j=0的情况赋值为inf。②、更新要及时。③、根据ai的范围,inf需要大于1010
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define ll long long
using namespace std;
const ll inf=1e17;
const int N=1e5+10;
char s[N];
int a[N],n;
ll dp[N][5]; ///1:不出现h 2:不出现ha 3:不出现har 4:不出现hard
char hard[]="#hard";
int main ()
{
cin>>n;
scanf("%s",s+1);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for (int i=1;i<=n;i++) dp[i][0]=inf;
if(s[1]=='h') dp[1][1]=a[1];
for(int i=2;i<=n;i++)
{
for(int j=1;j<=4;j++)
{
if(s[i]!=hard[j])
{
dp[i][j]=dp[i-1][j];
continue;
}
dp[i][j]=min(dp[i-1][j-1],dp[i-1][j]+a[i]);
}
}
printf("%lld\n",dp[n][4]);
return 0;
}