题目链接:Codeforces - Hard problem
每个串要么反转,要么不反转。所以我们可以想到dp
进而,我们可以去思考状态表示:dp[i][0/1]
分别表示前i个,第i个是否反转的最小费用。
然后转移方程就很简单了,可以看代码。
AC代码:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
string str[N],rev[N]; int c[N],dp[N][2],n;
signed main(){
cin>>n; memset(dp,0x3f,sizeof dp);
for(int i=1;i<=n;i++) cin>>c[i];
for(int i=1;i<=n;i++) cin>>str[i];
for(int i=1;i<=n;i++)
for(int j=str[i].size()-1;j>=0;j--) rev[i]+=str[i][j];
dp[1][0]=0,dp[1][1]=c[1];
for(int i=2;i<=n;i++){
if(str[i]>=str[i-1]) dp[i][0]=min(dp[i][0],dp[i-1][0]);
if(str[i]>=rev[i-1]) dp[i][0]=min(dp[i][0],dp[i-1][1]);
if(rev[i]>=str[i-1]) dp[i][1]=min(dp[i][1],dp[i-1][0]+c[i]);
if(rev[i]>=rev[i-1]) dp[i][1]=min(dp[i][1],dp[i-1][1]+c[i]);
}
if(min(dp[n][1],dp[n][0])==0x3f3f3f3f3f3f3f3f) puts("-1");
else cout<<min(dp[n][0],dp[n][1]);
return 0;
}