<题目链接>
题目大意:
给你一个字符串,每个字符有权值,问现在删除字符串中的字符使其中没有"hard"的最小代价是多少。
解题分析:
用DP来求解: 转载于 >>>
dp[i][1]:表示字符串s的前i个字符中不含有前缀'h'的最小代价
dp[i][2]:表示字符串s的前i个字符中不含有前缀'ha'的最小代价
dp[i][3]:表示字符串s的前i个字符中不含有前缀'har'的最小代价
dp[i][4]:表示字符串s的前i个字符中不含有前缀'hard'的最小代价
对于状态转移,例如对dp[i][3],如果位置i的字符不是r,那么dp[i][3] = dp[i - 1][3];
否则,要么去掉位置i的字符,则代价为dp[i - 1][3] + a[i],如果不去除该位置字符,那么之前的序列不能含有'ha',则代价为dp[i - 1][2]。
#include <bits/stdc++.h> using namespace std; #define N int(1e5+7) typedef long long ll; ll dp[N][5],arr[N]; char s[N]; const ll INF = 1e18; const char str[]="0hard"; int main(){ int n;scanf("%d",&n); scanf("%s",s+1); for(int i=1;i<=n;i++)scanf("%d",&arr[i]); for(int i=1;i<=n;i++)dp[i][0]=INF; if(s[1]=='h')dp[1][1]=arr[1]; for(int i=2;i<=n;i++) for(int j=1;j<=4;j++){ if(s[i]!=str[j])dp[i][j]=dp[i-1][j]; else dp[i][j]=min(dp[i-1][j]+arr[i],dp[i-1][j-1]); //以j=3为例,dp[i-1][j]为前i-1项不含'har',并且去除第j项的'r'的代价(因为前i-1项可能包含'ha'),dp[i-1][j-1]表示前i-1项连'ha'都不包含 } printf("%lld\n",dp[n][4]); }
一维的写法:
#include <bits/stdc++.h> using namespace std; typedef long long ll; ll dp[5]; char s[int(1e5+7)]; const char ss[]="0hard"; int main(){ int n;cin>>n; scanf("%s",s+1); for(int i=1;i<=n;i++){ ll now;scanf("%lld",&now); if(s[i]=='h')dp[1]+=now; for(int j=2;j<=4;j++) if(s[i]==ss[j])dp[j]=min(dp[j]+now,dp[j-1]); } printf("%lld\n",dp[4]); }
2019-02-17