题意:给出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<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
#define maxn 100010
#define LL long long
const LL INF=1e15;
int c[maxn];
string str[maxn][2];
LL dp[maxn][2];
string reverse(string s)
{
string res=s;
int i,len=res.length();
for(i=0;i<len/2;++i)
swap(res[i],res[len-1-i]);
return res;
}
int main()
{
int n,i;
while(scanf("%d",&n)!=EOF)
{
for(i=0;i<n;++i)
scanf("%d",&c[i]);
for(i=0;i<n;++i)
{
cin>>str[i][0];
str[i][1]=reverse(str[i][0]);
}
for(i=0;i<n;++i)
dp[i][0]=dp[i][1]=INF;
dp[0][0]=0; dp[0][1]=c[0];
for(i=1;i<n;++i)
{
if(str[i][0]>=str[i-1][0])
dp[i][0]=dp[i-1][0];
if(str[i][1]>=str[i-1][0])
dp[i][1]=dp[i-1][0]+c[i];
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][1])
dp[i][1]=min(dp[i][1],dp[i-1][1]+c[i]);
if(dp[i][1]==INF&&dp[i][0]==INF)
break;
}
if(i==n)
printf("%I64d\n",min(dp[n-1][0],dp[n-1][1]));
else
printf("-1\n");
}
return 0;
}