codeforces706C
Hard problem
现在有 n 个由小写字母组成的字符串。他想要让这些字符串按字典序排列,但是他不能交换任意两个字符串。他唯一能做的事是翻转字符串。
翻转第 i 个字符串需要花费 ci 的能量。他想知道将所有字符串排序最少要多少能量。
两个相邻的字符串可以相等,不一定要严格递增。
Input
第一行包含一个整数 n (2 ≤ n ≤ 100 000) — 表示字符串的数量。
第二行包含 n 个整数 ci (0 ≤ ci ≤ 109),第 i 个整数等于翻转第 i 个字符串所需的能量。
之后 n 行,每行包含一个小写英文字母。总长度不到 100 000。
Output
如果不可能有序,输出 - 1。否则输出最小所需的能量。
Example
2
1 2
ba
ac
1
3
1 3 1
aa
ba
ac
1
2
5 5
bbb
aaa
-1
2
3 3
aaa
aa
-1
Note
第二个样例中翻转字符串 2 或字符串 3。翻转字符串 3 所需能量更少。
第三个样例不合法,所以输出 - 1。
第四个样例不合法,所以输出 - 1。
sol:dp较为明显,因为i-2及之前的翻转是不影响当前的转移的,dp[i][0/1]表示在第i个字符串,当前是否翻转
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read()
{
ll s=;
bool f=;
char ch=' ';
while(!isdigit(ch))
{
f|=(ch=='-'); ch=getchar();
}
while(isdigit(ch))
{
s=(s<<)+(s<<)+(ch^); ch=getchar();
}
return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
if(x<)
{
putchar('-'); x=-x;
}
if(x<)
{
putchar(x+''); return;
}
write(x/);
putchar((x%)+'');
return;
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('\n')
const int N=;
int n;
ll Cost[N],dp[N][];
char S_Last[N],S_Now[N];
inline bool Judge(char *S1,char *S2)
{
int i,n1=strlen(S1+),n2=strlen(S2+);
for(i=;i<=min(n1,n2);i++) if(S1[i]!=S2[i])
{
return S1[i]<S2[i];
}
return (n1<=n2)?:;
}
int main()
{
int i,j;
R(n);
for(i=;i<=n;i++) R(Cost[i]);
scanf("%s",S_Last+);
memset(dp,,sizeof dp);
dp[][]=;
dp[][]=Cost[];
for(i=;i<=n;i++)
{
scanf("%s",S_Now+);
if(Judge(S_Last,S_Now))
{
dp[i][]=min(dp[i][],dp[i-][]);
}
reverse(S_Last+,S_Last+strlen(S_Last+)+);
if(Judge(S_Last,S_Now))
{
dp[i][]=min(dp[i][],dp[i-][]);
}
reverse(S_Now+,S_Now+strlen(S_Now+)+);
if(Judge(S_Last,S_Now))
{
dp[i][]=min(dp[i][],dp[i-][]+Cost[i]);
}
reverse(S_Last+,S_Last+strlen(S_Last+)+);
if(Judge(S_Last,S_Now))
{
dp[i][]=min(dp[i][],dp[i-][]+Cost[i]);
}
reverse(S_Now+,S_Now+strlen(S_Now+)+);
memmove(S_Last,S_Now,sizeof S_Last);
}
if(min(dp[n][],dp[n][])>) puts("-1");
else Wl(min(dp[n][],dp[n][]));
return ;
}
/*
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
*/
codeforces706C的更多相关文章
随机推荐
- PAT A1148 Werewolf - Simple Version (20 分)——暴力遍历,负负得正
Werewolf(狼人杀) is a game in which the players are partitioned into two parties: the werewolves and th ...
- windows7系统下配置开发环境 python2.7+pyqt4+pycharm
python2.7 链接:https://pan.baidu.com/s/1lPI9AF9GCaakLXsMZLd5mQ 提取码:5xt6 pip 链接:https://pan.baidu.com/s ...
- ubuntu 系统查看opencv 的版本
有很多的时候 ,我们想知道自己的电脑里面安装的opencv版本是多少 在终端中运行下面的命令. pkg-config --modversion opencv 为什么要知道自己电脑的opencv 版本, ...
- java从命令行接受多个数字求和输出
一·设计思路 1.定义一个整型变量sum,用于接收和 2.利用循环将命令行数字求和 3.输出参数个数以及参数之和 二·流程图 三·程序源代码 public class JavaAppArguments ...
- (转)怎么实时查看mysql当前连接数
1.查看当前所有连接的详细资料: ./mysqladmin -uadmin -p123456 -h127.0.0.1 processlist 2.只查看当前连接数(Threads就是连接数.): ./ ...
- LeetCode112:Path Sum
正常写法 bool HasPathSum(TreeNode root, int sum) { bool ret=false; if(root==null)return false; if(root.l ...
- Linux安装RabbitMq-Centos7版本
一.Linux系统中安装RabbitMQ 由于RabbitMQ依赖于Erlang,所以先要在机器上安装Erlang环境 单机版 1.安装GCC GCC-C++ Openssl等模块 yum -y in ...
- LOJ2541 PKUWC2018 猎人杀 期望、容斥、生成函数、分治
传送门 首先,每一次有一个猎人死亡之后\(\sum w\)会变化,计算起来很麻烦,所以考虑在某一个猎人死亡之后给其打上标记,仍然计算他的\(w\),只是如果打中了一个打上了标记的人就重新选择.这样对应 ...
- 转 Velocity中加载vm文件的三种方式
Velocity中加载vm文件的三种方式 velocitypropertiespath Velocity中加载vm文件的三种方式: 方式一:加载classpath目录下的vm文件 Prope ...
- Luogu P3177 [HAOI2015]树上染色
一道有机结合了计数和贪心这一DP两大考点的神仙题,不得不说做法是很玄妙. 首先我们很容易想到DP,设\(f_{i,j}\)表示在以\(i\)为根节点的子树中选\(j\)个黑色节点的最大收益值. 然后我 ...