题解来自:http://blog.csdn.net/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;
}