Codeforces Round #367 (Div. 2) C. Hard problem
题目连接:http://codeforces.com/contest/706/problem/C
题意:
有n个字符串,对第i个字符串进行反转操作代价为ci。
要使n个字符串按照字典序从小到大排列,最小的代价是多少。
分析:
dp[i][0]代表前i个串有序且第i个串不反转的代价
dp[i][1]代表前i个串有序且第i个串反转的代价
初始化 dp[0][0]=0,dp[0][1] = c[0]
然后当字典序满足有小到大时进行递推
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<algorithm> #include<map> #include<cstring> #include<string> #include<iostream> #include<set> #include<vector> #include<cmath> using namespace std; typedef long long ll; const int mod = 1000000000+7; const int maxn = 100010; int x[maxn]; ll ans,c[maxn]; string s[maxn]; ll dp[maxn][2]; const ll INF = 4557430888798830399LL; int main() { int n; while(~scanf("%d",&n)) { for(int i=0;i<n;i++) cin>>c[i]; for(int i=0;i<n;i++) cin>>s[i]; memset(dp,0x3f,sizeof(dp)); dp[0][0] = 0; dp[0][1] = c[0]; string rs1,rs2; for(int i=1;i<n;i++) { rs1 = s[i-1]; rs2 = s[i]; reverse(rs1.begin(),rs1.end()); reverse(rs2.begin(),rs2.end()); // if(s[i-1]>s[i] && rs1>s[i]) dp[i][0] = -1; // if(rs1>rs2 && s[i-1]>rs2) dp[i][1] = -1; if(s[i-1]<=s[i]) dp[i][0] = min(dp[i][0],dp[i-1][0]); if(rs1<=s[i]) dp[i][0] = min(dp[i][0],dp[i-1][1]); if(rs2>=s[i-1]) dp[i][1] = min(dp[i][1],dp[i-1][0]+c[i]); if(rs2>=rs1) dp[i][1] = min(dp[i][1],dp[i-1][1]+c[i]); // cout<<dp[i][0]<<' '<<dp[i][1]<<endl; } if(dp[n-1][0]<INF || dp[n-1][1]<INF) cout<<min(dp[n-1][0],dp[n-1][1])<<endl; else cout<<"-1"<<endl; } return 0; }