可爱的题目大意
给出一个长度为(n)的字符串,如果这个字符串中含有子序列(“hard”),那么这个字符串就很(hard)。你不希望这个字符串很(hard),所以想要从中删掉几个字符使他不(hard)。
例:(hard), (hzazrzd), (haaaaard) 都很 (hard),而 (har), (hart),(drah) 不 (hard)。
删掉在原字符串中的第(i)个字符需要花费(a_i)的代价,求最小代价。
(Solution)
我们令(f_{i,j})表示当前(dp)到第(i)位,清到(hard)的第几位(用当前位置消掉(hard))
对于一个可能的子序列(hard),我们只需要在其中任意删掉一个字符就可以消灭整个字符串,那么有
(f_{i,j}=min(f_{i-1,j-1},f_{i-1,j}+a_i))
然后我们发现第(i)层的状态只和(i-1)层的状态有关,于是就可以省掉一维(其实省掉一维的做法更好理解?)
(Code)
#include<bits/stdc++.h>
using namespace std;
namespace my_std
{
typedef long long ll;
typedef double db;
#define pf printf
#define pc putchar
#define fr(i,x,y) for(register ll i=(x);i<=(y);++i)
#define pfr(i,x,y) for(register ll i=(x);i>=(y);--i)
#define go(x) for(ll i=head[u];i;i=e[i].nxt)
#define enter pc('
')
#define space pc(' ')
#define fir first
#define sec second
#define MP make_pair
const ll inf=0x3f3f3f3f;
const ll inff=1e15;
inline ll read()
{
ll sum=0,f=1;
char ch=0;
while(!isdigit(ch))
{
if(ch=='-') f=-1;
ch=getchar();
}
while(isdigit(ch))
{
sum=sum*10+(ch^48);
ch=getchar();
}
return sum*f;
}
inline void write(ll x)
{
if(x<0)
{
x=-x;
pc('-');
}
if(x>9) write(x/10);
pc(x%10+'0');
}
inline void writeln(ll x)
{
write(x);
enter;
}
inline void writesp(ll x)
{
write(x);
space;
}
}
using namespace my_std;
const ll N=1e5+50;
ll n,a[N],f[5];
char s[N];
int main(void)
{
n=read();
scanf("%s",s+1);
fr(i,1,n) a[i]=read();
fr(i,1,n)
{
if(s[i]=='h') f[1]+=a[i];
else if(s[i]=='a') f[2]=min(f[2]+a[i],f[1]);
else if(s[i]=='r') f[3]=min(f[3]+a[i],f[2]);
else if(s[i]=='d') f[4]=min(f[4]+a[i],f[3]);
}
writeln(f[4]);
return 0;
}