Codeforces Round #367 (Div. 2) C

题意:给你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-6
typedef 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]的第一位移到最后一位。
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值