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\n", ans == LNF ? -1 : ans);
    }
    return 0;
}
时间: 2024-10-18 20:14:28

CodeForces 706C Hard problem (水DP)的相关文章

codeforces 706C Hard problem DP(动态规划)问题

题目链接:http://codeforces.com/problemset/problem/706/C 题目大意:  给定n个字符串, 每个字符串可以颠倒前后位置(第一个字母到最后一个,第二个字母到倒数第二位) 每次颠倒需要花费ci的力气, 要求将所给的n个字符串用最小力气按字典序排列, 输出力气值, 如果无法按字典序排列, 则输出-1 数据范围:2?≤?n?≤?100?000 . ci (0?≤?ci?≤?1e9) 所有字符串总长度不会超过1000000. 解题思路: 这是一道DP题, dp[

CodeForces 706C Hard problem

题意:给你很多字符串,每个字符串可以翻转,翻转有价值,让你求满足递增的字符串,如果不行就-1 思路:要么选,要么不选,线性dp 代码: #include <bits/stdc++.h> using namespace std; const int maxn=1e5+7; const long long INF=0x3f3f3f3f3f3f3f3fLL; string str[maxn][2]; int n,a[maxn]; long long dp[maxn][2]; string rever

CodeForces 706C dp

C - Hard problem Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice CodeForces 706C Description Vasiliy is fond of solving different tasks. Today he found one he wasn't able to solve himself, so he as

hdu5074 Hatsune Miku 2014鞍山现场赛E题 水dp

http://acm.hdu.edu.cn/showproblem.php?pid=5074 Hatsune Miku Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 325    Accepted Submission(s): 243 Problem Description Hatsune Miku is a popular vi

HDU 4968 (水dp 其他?)

1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <vector> 5 #include <map> 6 using namespace std; 7 const int inf = 0x3f3f3f3f; 8 const int MAX = 200+10; 9 double GPA[10],dp1[20][30000],dp2[20][30000

HDU 4960 (水dp)

Another OCD Patient Problem Description Xiaoji is an OCD (obsessive-compulsive disorder) patient. This morning, his children played with plasticene. They broke the plasticene into N pieces, and put them in a line. Each piece has a volume Vi. Since Xi

Codeforces 803E--Roma and Poker (DP)

原题链接:http://codeforces.com/problemset/problem/803/E 题意:给一个n长度的字符串,其中'?'可以替换成'D'.'W'.'L'中的任意一种,'D'等价于0, 'W'等价于1.'L'等价于-1.输出所有'?'被替换掉后,W和L的数目之差为k,且任意一个[1, i]的子串中W和L数目之差不能等于k. 思路:用DP做.定义bool dp[i][j]代表前i个字符W和L数目之差为j, -k<=j<=k(在数组中范围为[0, 2*k]),那么当str[i]

codeforces 825F F. String Compression dp+kmp找字符串的最小循环节

/** 题目:F. String Compression 链接:http://codeforces.com/problemset/problem/825/F 题意:压缩字符串后求最小长度. 思路: dp[i]表示前i个字符需要的最小次数. dp[i] = min(dp[j]+w(j+1,i)); (0<=j<i); [j+1,i]如果存在循环节(自身不算),那么取最小的循环节x.w = digit((i-j)/x)+x; 否则w = i-j+1; 求一个区间最小循环节: 证明:http://w

Codeforces 758D Ability To Convert dp

题目链接: http://codeforces.com/problemset/problem/758/D 题意: 一个n进制下的数k,其中k不会用字母,如果有A就用10代替了.求k这个数对应的,在10进制下最小的数. 思路: 来自:http://www.cnblogs.com/TreeDream/p/6322755.html 本质上是把数字分成若干段使得每一段 <n 且没有前导 0 dp[i] 表示前 i 个字符划分好之后能得到的最小数. 状态枚举下一段怎么切. 枚举每一个分割点,对什么进行更新