CF1096D Easy Problem(DP)
题意:给出一个字符串,去掉第i位的花费为a[i],求使字符串中子串不含hard的最小代价。
题解:这题的思路还是比较套路的,
dp[i][kd]两维,kd=0表示不含d的最小花费,1表示不含rd的,2表示不含ard的,3表示不含hard的
那么转移方程就显而易见了,一言概之就是如果前面没有,我这也要没有,就这位一定要去,否则不用去
代码如下:
#include<bits/stdc++.h> using namespace std; int n,a[100010]; char s[100010]; long long dp[100010][4]; int main() { scanf("%d",&n); scanf("%s",s+1); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } for(int i=n;i>=1;i--) { 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]; if(s[i]=='d') { dp[i][0]=dp[i+1][0]+a[i]; dp[i][1]=min(dp[i+1][0],dp[i+1][1]); } if(s[i]=='r') { dp[i][1]=dp[i+1][1]+a[i]; dp[i][2]=min(dp[i+1][1],dp[i+1][2]); } if(s[i]=='a') { dp[i][2]=dp[i+1][2]+a[i]; dp[i][3]=min(dp[i+1][2],dp[i+1][3]); } if(s[i]=='h') { dp[i][3]=dp[i+1][3]+a[i]; } } long long ans=0; ans=min(min(dp[1][0],dp[1][1]),min(dp[1][2],dp[1][3])); printf("%lld\n",ans); } #include<bits/stdc++.h> using namespace std; int n,a[100010]; char s[100010]; long long dp[100010][4]; int main() { scanf("%d",&n); scanf("%s",s+1); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } for(int i=n;i>=1;i--) { 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]; if(s[i]=='d') { dp[i][0]=dp[i+1][0]+a[i]; dp[i][1]=min(dp[i+1][0],dp[i+1][1]); } if(s[i]=='r') { dp[i][1]=dp[i+1][1]+a[i]; dp[i][2]=min(dp[i+1][1],dp[i+1][2]); } if(s[i]=='a') { dp[i][2]=dp[i+1][2]+a[i]; dp[i][3]=min(dp[i+1][2],dp[i+1][3]); } if(s[i]=='h') { dp[i][3]=dp[i+1][3]+a[i]; } } long long ans=0; ans=min(min(dp[1][0],dp[1][1]),min(dp[1][2],dp[1][3])); printf("%lld\n",ans); }