Codeforces Round #367 (Div. 2) C

来源:互联网 发布:wine for mac下载 编辑:程序博客网 时间:2024/06/05 15:45

题意:给你N个字符串,以及改变这N个字符串的花费,要求你使得这N个字符串最后的顺序满足字典序,可以选择改变第i个字符串也可以选择不改变,改变的方法是把字符串反转。 问你最小的花费。

解法: We will solve the problem with the help of dynamic programming.

dp[i][j] is the minimum amount of energy that should be spent to make first i strings sorted in lexicographical order and i-th of them will be reversed if j = 1 and not reversed if j = 0.

dp[i][j] is updated by dp[i - 1][0] and dp[i - 1][1].

It remains to verify that the i-th string is lexicographically greater than (i - 1)-th (if j = 1 then we should check reversed i-th string, similar to (i - 1)-th).

Then we update

dp[i][j] = min(dp[i][j], dp[i - 1][0] + c[i] * j), dp[i][j] = min(dp[i][j], dp[i - 1][1] + j * c[i]).

The answer is a minimum of dp[n][0] and dp[n][1].

Time Complexity: O(n+sum_length).

#include <bits/stdc++.h>#define _ ios_base::sync_with_stdio(0);cin.tie(0);#define INF 0x3f3f3f3f#define eps 1e-6typedef long long LL;const double pi = acos(-1.0);const long long mod = 1e9 + 2015;using namespace std;LL a[100005];string s1[100005];string s2[100005];LL dp[100005][2];int main(){    ios_base::sync_with_stdio(false); cin.tie(0);    //freopen("int.txt","r",stdin);    //freopen("out.txt","w",stdout);    int N;    cin >> N;    for(int i = 1;i <= N;i++)    {        cin >> a[i];        dp[i][0] = dp[i][1] = 1e15;    }    for(int i = 1;i <= N;i++)    {        cin >> s1[i];        s2[i] = s1[i];        reverse(s2[i].begin(),s2[i].end());    }    dp[1][0] = 0,dp[1][1] = a[1];    for(int i = 2;i <= N;i++)    {        if(s1[i] >= s1[i - 1])            dp[i][0] = min(dp[i][0],dp[i - 1][0]);        if(s1[i] >= s2[i - 1])            dp[i][0] = min(dp[i][0],dp[i - 1][1]);        if(s2[i] >= s1[i - 1])            dp[i][1] = min(dp[i][1],dp[i - 1][0] + a[i]);        if(s2[i] >= s2[i - 1])            dp[i][1] = min(dp[i][1],dp[i - 1][1] + a[i]);    }    LL ans = min(dp[N][1],dp[N][0]);    if(ans != 1e15)        printf("%I64d\n",ans);    else        puts("-1");    return 0;}

PS:开始把题意给理解错了,理解成把第一个字符放到最后一位去。

for(int i = 1;i <= N;i++)    {        cin >> s1[i];        char c = s1[i][0];        s2[i] = s1[i].substr(1);        s2[i] += c;        //s2[i]代表把s1[i]的第一位移到最后一位。    }
0 0
原创粉丝点击