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]

然后当字典序满足有小到大时进行递推

 

代码:

#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;
}
View Code

 

posted @ 2016-08-12 11:46  fukan  阅读(218)  评论(0编辑  收藏  举报