- Easy Problem
- 思路:设dp [ i ] [ j ] 表 示 前 i 位 匹 配 了 hard 的 前 j 个 字 符,破 坏 掉 需 要 的 最 小 的 代 价 。
- 破 毁 掉 前 1 个 只 能 破 坏 自 己,坏 掉 前 两 个 可以通过破坏第一个 或第二个 ,依次类推,按顺序转移
- dp [ i ] [ 3 ] 转移 是min ( d p [ i - 1 ] [ 3 ], d p [ i - 1 ] [ 2 ] ); 而dp[ i ] [ 2 ] =min ( dp [ i - 1 ] [ 1 ],dp [ i - 1 ] [ 2 ]);
- 这样 dp[ i ][ 3 ]就是 在破坏 第一个 第二个 第三个 中 取了最小值。
- 长度为 nnn 的字符串每个字符都有其消除花费权值,使用最小的花费消除字符使字符串中不存在
hard
(非必须连续) - 考虑动态规划,对于字符
a
来说转移方程为:dp[ i − 1] [ 0 ] 是把 i 位置之前(不包括 i )的字符h
全部清除, - dp[ i ] [ 1 ]+cost[ i ]是把 iii 位置之前(包括 i )的字符
a
全部清除,两者取最小值即可,其余字符r
、d
同理。 -
#include<bits/stdc++.h> using namespace std; #define ll long long #define maxn 123456 const ll inf=1e17; ll n,a[maxn],dp[maxn][5],x; char str[maxn]; int main() { scanf("%lld%s",&n,str); for(int i=1; i<=n; i++) { scanf("%lld",&x); if(str[i-1]=='h') { dp[i][0]=dp[i-1][0]+x; dp[i][1]=min(dp[i-1][1],dp[i-1][0]); dp[i][2]=dp[i-1][2]; dp[i][3]=dp[i-1][3]; } else if(str[i-1]=='a') { dp[i][0]=dp[i-1][0]; dp[i][1]=dp[i-1][1]+x; dp[i][2]=min(dp[i-1][1],dp[i-1][2]); dp[i][3]=dp[i-1][3]; } else if(str[i-1]=='r') { dp[i][0]=dp[i-1][0]; dp[i][1]=dp[i-1][1]; dp[i][2]=dp[i-1][2]+x; dp[i][3]=min(dp[i-1][3],dp[i-1][2]); } else if(str[i-1]=='d') { dp[i][0]=dp[i-1][0]; dp[i][1]=dp[i-1][1]; dp[i][2]=dp[i-1][2]; dp[i][3]=dp[i-1][3]+x; } else { dp[i][0]=dp[i-1][0]; dp[i][1]=dp[i-1][1]; dp[i][2]=dp[i-1][2]; dp[i][3]=dp[i-1][3]; } } printf("%lld\n",min(min(dp[n][0],dp[n][1]),min(dp[n][2],dp[n][3]))); return 0; }
- 或者记忆化:直接dp[i][j]表示放了i个数匹配hard匹配到了第j位。每次决策有两种。
删除:代价ai,强制j保持不变。 不删除:无代价,j根据s[i]是否和j+1匹配来决定是否+1。 -
#include<bits/stdc++.h> using namespace std; #define inf 1e18 #define maxn 123456 #define ll long long ll dp[maxn][10],n,a[maxn]; char str[maxn]; char s[5]= {'h','a','r','d'}; ll dfs(int id,int k) { if(id==n+1)return 0; if(dp[id][k]!=-1)return dp[id][k]; dp[id][k]=inf; if(str[id]==s[k+1]) { if(k!=2)dp[id][k]=min(dp[id][k],dfs(id+1,k+1)); } else dp[id][k]=min(dp[id][k],dfs(id+1,k)); dp[id][k]=min(dp[id][k],dfs(id+1,k)+a[id]); return dp[id][k]; } int main() { memset(dp,-1,sizeof(dp)); scanf("%lld%s",&n,str+1); for(int i=1; i<=n; i++) scanf("%lld",&a[i]); printf("%lld\n",dfs(1,-1)); return 0; }
Easy Problem-简单DP
最新推荐文章于 2022-05-03 20:45:35 发布