zoukankan      html  css  js  c++  java
  • 【CF706C】Hard problem

    Description

    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.

    Sample Input

    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
    

    Hint

    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.


    【题解】

    意思是说每个字符串只能倒转或不倒转。(逆序)

    然后要求n个字符串最后为有序的。s[i]>=s[i-1];

    每个字符串倒转都需要耗费能量c[i]

    设f[i][0]表示第i个字符串不倒转所需要的最少能量。

    f[i][1]表示第i个字符串倒转所需要的最少能量。

    然后用一个结构体记录每一个字符不倒转的样子和倒转过后的样子。->zhengs,fans;

    因为你在处理第I个,如果前i-1个不是升序的。那改变第i个毫无意义。

    所以如果f[i][0]==-1或f[i][1] ==-1,则表示这个状态不符合升序的要求。不能由这个状态推出下一个状态。

    然后每次把存zhengs和fans的a[]数组的a[i].zhengs->a[i-1].fans,a[i-1].zhengs(对应f[i-1][1],f[i-1][0])进行比较如果满足a[i].zhengs>=后面两个字符则f[i][0]=min(f[i-1][0],f[i-1][1]);前提是f[i-1][0]或f[i-1][1]这个状态存在!

    然后a[i].fans->a[i-1].fans,a[i-1].zhengs(对应f[i-1][1],f[i-1][0]).如果满足a[i].fans>=后面两个字符串。则f[i][1]和f[i-1][0]或f[i-1][1]取较小值。同样要求这个状态要存在才行!

    【代码】

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <iostream>
    
    using namespace std;
    
    struct ss
    {
    	string zhengs, fans;//用来存正的序列和反向之后的序列。
    };
    
    ss a[100001];
    __int64 f[100001][2], c[100001];
    int n;
    
    int main()
    {
    	//freopen("F:\rush.txt", "r", stdin);
    	//freopen("F:\rush_out.txt", "w", stdout);
    	scanf("%d", &n);
    	for (int i = 1; i <= n; i++)//读入对某一个操作需要的能量值。
    		scanf("%I64d", &c[i]);
    	char s[100001];
    	for (int i = 1; i <= n; i++)//读入n个字符串
    	{
    		scanf("%s", s);//用scanf读会快一点。
    		a[i].zhengs = string(s);
    		a[i].fans = string(s);
    		int begin = 0, end = a[i].zhengs.size() - 1;
    		while (begin <= end)//进行反转的过程
    		{
    			a[i].fans[begin] = a[i].zhengs[end];
    			a[i].fans[end] = a[i].zhengs[begin];
    			begin++; end--;
    		}
    	}
    	memset(f, 255, sizeof(f));//一开始所有的状态都无法到达。
    	f[1][0] = 0; f[1][1] = c[1];//初值表示前1个字符串,不反转则消耗为0,翻转则消耗为c[1]
    	for (int i = 2; i <= n; i++)
    	{
    		if (a[i].zhengs >= a[i - 1].zhengs && f[i - 1][0] != -1)//根据上面题解的规则写转移就可以了。
    			f[i][0] = f[i - 1][0];
    		if (a[i].zhengs >= a[i - 1].fans && f[i - 1][1] != -1)
    			if (f[i][0] == -1 || f[i][0] > f[i - 1][1])
    				f[i][0] = f[i - 1][1]; //要注意。一定要f[i-1][x]这个状态存在才能转移。
    		if (a[i].fans >= a[i - 1].zhengs && f[i - 1][0] != -1)
    			f[i][1] = f[i - 1][0] + c[i];
    		if (a[i].fans >= a[i - 1].fans && f[i - 1][1] != -1)
    			if (f[i][1] == -1 || f[i][1] > f[i - 1][1] + c[i])
    				f[i][1] = f[i - 1][1] + c[i];
    	}
    	__int64 ans = f[n][1];//最后取f[n][1],f[n][0]中的较小值
    	if (f[n][0] < f[n][1])
    		ans = f[n][0];//如果较小值是-1,就取f[n][1],f[n][0]中的较大值。
    	if (ans == -1) //如果最小值是-1,则取最大值。这样就能指向答案了(当然,如果还是-1则答案是-1)
    	{
    		__int64 temp = f[n][1];
    		if (f[n][0] > f[n][1])
    			temp = f[n][0];
    		ans = temp;
    	}
    	printf("%I64d", ans);
    	return 0;
    }


  • 相关阅读:
    Android 修改应用程序字体
    Activity A 跳转到Activity B 生命周期
    Android调用系统设置
    最近遇到adb connection 问题,总结一下
    今日写一篇散文 Textview settext 方法不能放入 int 参数 不然报错!
    计时线程Runnable和Handler的结合
    JMF 下载安装与测试 测试成功
    基本数据类型的介绍及转换,基本数据类型与字符串之间转换,字符串与字符数组之间转换以及字符串与字节数组之间转换
    超实用的Eclipse快捷键大全(解密为什么他们的代码写的又快又好~)
    JDK的下载、安装及Eclipse安装详细教程(内附:网盘win64版JDK安装包)
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7632287.html
Copyright © 2011-2022 走看看