codeforces706C Hard problem 动态规划

探讨如何通过反转字符串并最小化消耗的能量来实现字符串的字典序排序。使用动态规划解决字符串排序问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C. Hard problem
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Vasiliy is fond of solving different tasks. Today he found one he wasn't able to solve himself, so he asks you to help.

Vasiliy is given n strings consisting of lowercase English letters. He wants them to be sorted in lexicographical order (as in the dictionary), but he is not allowed to swap any of them. The only operation he is allowed to do is to reverse any of them (first character becomes last, second becomes one before last and so on).

To reverse the i-th string Vasiliy has to spent ci units of energy. He is interested in the minimum amount of energy he has to spent in order to have strings sorted in lexicographical order.

String A is lexicographically smaller than string B if it is shorter than B (|A| < |B|) and is its prefix, or if none of them is a prefix of the other and at the first position where they differ character in A is smaller than the character in B.

For the purpose of this problem, two equal strings nearby do not break the condition of sequence being sorted lexicographically.

Input

The first line of the input contains a single integer n (2 ≤ n ≤ 100 000) — the number of strings.

The second line contains n integers ci (0 ≤ ci ≤ 109), the i-th of them is equal to the amount of energy Vasiliy has to spent in order to reverse the i-th string.

Then follow n lines, each containing a string consisting of lowercase English letters. The total length of these strings doesn't exceed100 000.

Output

If it is impossible to reverse some of the strings such that they will be located in lexicographical order, print  - 1. Otherwise, print the minimum total amount of energy Vasiliy has to spent.

Examples
input
2
1 2
ba
ac
output
1
input
3
1 3 1
aa
ba
ac
output
1
input
2
5 5
bbb
aaa
output
-1
input
2
3 3
aaa
aa
output
-1
Note

In the second sample one has to reverse string 2 or string 3. To amount of energy required to reverse the string 3 is smaller.

In the third sample, both strings do not change after reverse and they go in the wrong order, so the answer is  - 1.

In the fourth sample, both strings consists of characters 'a' only, but in the sorted order string "aa" should go before string "aaa", thus the answer is  - 1.



题解来自:http://blog.youkuaiyun.com/zwj1452267376/article/details/52188231



题意:给出n个字符串(妈的是字符串啊,不是字符啊zz),可以颠倒任意一个字符串,颠倒每个字符串都有其对应的花费ci。经过操作后是否能满足字符串str[i]>=str[i-1],能输出最小花费,不能输出-1


注意:所有字符串加起来长度不超过100000,我看成每一个了,觉得怎么做都要炸


题解:因为不知道单个字符串具体长度,所以不能开字符串数组存储了(想了一下滚动数组,也可以)。这里string大法好啊。然后dp[i][0/1]表示第i个字符串是否颠倒(0表示不颠倒,1表示颠倒)的状态下满足字符串str[i]>=str[i-1]的最小花费。转态转移中判断各种使得str[i]>=str[i-1]的各种情况就可以了。


#include <cstdio>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <string>
#include <algorithm>
#define PAUSE system("pause")

using namespace std;

typedef long long ll;
const int maxn = 100000;
const ll INF = 1e15;
string str[maxn + 5][2];
ll dp[maxn + 5][2];
int n, c[maxn + 5];

string rev(string s) {
	string ts = s;
	int len = ts.length();
	for (int i = 0; i < len / 2; i++) {
		swap(ts[i], ts[len - i - 1]);
	}
	return ts;
}

int main()
{
	cin >> n;
	for (int i = 0; i < n; i++) {
		scanf("%d", &c[i]);
	}
	for (int i = 0; i < n; i++) {
		string s;
		cin >> s;
		str[i][0] = s;
		str[i][1] = rev(s);

		//cout << str[i][0] << endl; //debug
		//cout << str[i][1] << endl;
		//PAUSE;

	}
	for (int i = 0; i < n; i++) {
		dp[i][0] = dp[i][1] = INF;
	}
	dp[0][0] = 0; dp[0][1] = c[0];
	int i;
	for (i = 1; i < n; i++) {
		if (str[i][0] >= str[i - 1][0])
			dp[i][0] = dp[i - 1][0];
		if (str[i][0] >= str[i - 1][1]) {
			dp[i][0] = min(dp[i][0], dp[i - 1][1]);
		}
		if (str[i][1] >= str[i - 1][0]) {
			dp[i][1] = dp[i - 1][0] + c[i];
		}
		if (str[i][1] >= str[i - 1][1]) {
			dp[i][1] = min(dp[i][1], dp[i - 1][1] + c[i]);
		}
		if (dp[i][0] == INF && dp[i][1] == INF) {
			break;
		}
	}
	if (i == n) {
		printf("%I64d\n", min(dp[n - 1][0], dp[n - 1][1]));
	}
	else {
		puts("-1");
	}
	return 0;
}



### Codeforces Div4 比赛难度等级 Codeforces的比赛通常按照不同的分组来划分参赛者,而Div.4是专门为较低评级的选手设计的比赛。这类比赛允许rating在1400或更低的参与者加入[^1]。 对于题目难度分布,在一场典型的Codeforces比赛中,会有一系列按字母顺序排列的任务,从最简单的A类问题到更复杂的后续任务(如B、C等)。每道题目的预期解决难度随着字母表位置增加而上升。然而具体针对Div.4赛事而言: - **简单入门级挑战**:像A和B这样的早期问题是相对容易处理的,旨在测试基本概念理解和编程技能的基础应用。 - **中级复杂度**:接下来的问题比如C和D则需要更多的算法知识以及解决问题的能力,尽管仍然保持在一个较为基础的水平上以便适合新接触竞赛编程的人群参与进来并获得成长的机会。 - **高级但可控**:最后几道题E及以上可能会涉及到更加深入的数据结构或是优化技巧等内容;不过即便如此,在Div.4里这些难题也会被调整得让目标群体能够触及,鼓励大家不断进步的同时不至于感到过分挫败。 值得注意的是,虽然上述描述提供了一个大致框架用于理解Div.4比赛内各层次试题的大致定位,但是每次具体的赛事设置仍取决于命题团队的选择,并且实际难易程度也可能因个人背景差异有所不同。 ```python # 示例代码展示如何判断一个问题属于哪个难度范围 def determine_problem_difficulty(rating): if rating <= 800: return "Very Easy" elif 800 < rating <= 1200: return "Easy" elif 1200 < rating <= 1600: return "Medium" elif 1600 < rating <= 2000: return "Hard" else: return "Very Hard" print(determine_problem_difficulty(750)) # 输出 Very Easy ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值