zoukankan      html  css  js  c++  java
  • CodeForces 706C Hard problem (水DP)

    题意:对于给定的n个字符串,可以花费a[i]  将其倒序,问是否可以将其排成从大到小的字典序,且花费最小是多少。

    析:很明显的水DP,如果不是水DP,我也不会做。。。。

    这个就要二维,d[2][maxn],d[0][i]表示第 i 个不反转是最小花费,d[1][i]表示第 i 个反转最小花费,那么剩下的就很简单了么,

    代码如下:

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include <cstdio>
    #include <string>
    #include <cstdlib>
    #include <cmath>
    #include <iostream>
    #include <cstring>
    #include <set>
    #include <queue>
    #include <algorithm>
    #include <vector>
    #include <map>
    #include <cctype>
    #include <stack>
    using namespace std;
    
    typedef long long LL;
    typedef pair<int, int> P;
    const int INF = 0x3f3f3f3f;
    const double inf = 0x3f3f3f3f3f3f;
    const LL LNF = 100000000000000000;
    const double PI = acos(-1.0);
    const double eps = 1e-8;
    const int maxn = 1e5 + 5;
    const int mod = 1e9 + 7;
    const char *mark = "+-*";
    const int dr[] = {-1, 0, 1, 0};
    const int dc[] = {0, 1, 0, -1};
    int n, m;
    inline bool is_in(int r, int c){
        return r >= 0 && r < n && c >= 0 && c < m;
    }
    inline LL Max(LL a, LL b){  return a < b ? b : a; }
    inline LL Min(LL a, LL b){  return a > b ? b : a; }
    int a[maxn];
    vector<string> v1;
    vector<string> v2;
    LL d[2][maxn];
    
    int main(){
        while(scanf("%d", &n) == 1){
            for(int i = 0; i < n; ++i)  scanf("%d", &a[i]);
            string s;
            v1.clear();  v2.clear();
            for(int i = 0; i < n; ++i){
                cin >> s;
                v1.push_back(s);
                reverse(s.begin(), s.end());
                v2.push_back(s);
            }
            fill(d[0], d[0]+n, LNF);
            fill(d[1], d[1]+n, LNF);
            d[0][0] = 0, d[1][0] = a[0];
            for(int i = 1; i < n; ++i){
                if(v1[i-1] <= v1[i]) d[0][i] = Min(d[0][i], d[0][i-1]);
                if(v1[i-1] <= v2[i]) d[1][i] = Min(d[1][i], d[0][i-1]+a[i]);
                if(v2[i-1] <= v1[i]) d[0][i] = Min(d[0][i], d[1][i-1]);
                if(v2[i-1] <= v2[i]) d[1][i] = Min(d[1][i], d[1][i-1]+a[i]);
                if(d[1][i] == LNF && d[0][i] == LNF)   break;
            }
            LL ans = Min(d[0][n-1], d[1][n-1]);
            printf("%I64d
    ", ans == LNF ? -1 : ans);
        }
        return 0;
    }
    
  • 相关阅读:
    mybatis强化(二)Parameters和Result
    operator new 和 new operator
    hdu 1007 Quoit Design 分治求最近点对
    实现一个简单的shared_ptr
    bzoj 3224: Tyvj 1728 普通平衡树 替罪羊树
    bzoj 2648 SJY摆棋子 kd树
    hdu 2966 In case of failure k-d树
    codeforces 713D D. Animals and Puzzle 二分+二维rmq
    bzoj 1188 : [HNOI2007]分裂游戏 sg函数
    bzoj 1912 : [Apio2010]patrol 巡逻 树的直径
  • 原文地址:https://www.cnblogs.com/dwtfukgv/p/5767735.html
Copyright © 2011-2022 走看看