1. 程式人生 > >Codeforces Round #367 (Div. 2) C. Hard problem (dp)

Codeforces Round #367 (Div. 2) C. Hard problem (dp)

Note

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個串,要你求:要使這n個串的字典序從小到大,要消耗的費用最小是多少。改變字典序只能通過反串來改變。

dp[i][0]表示到第i個字串,第i個字串不翻轉,能消耗的最小值。


dp[i][1]表示到第i個字串,第i個字串翻轉,能消耗的最小值。

詳細看程式碼。

AC程式碼:

#pragma comment(linker, "/STACK:102400000,102400000")
//#include<bits/stdc++.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<map>
#include<cmath>
#include<queue>
#include<set>
#include<stack>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define mst(a) memset(a, 0, sizeof(a))
#define M_P(x,y) make_pair(x,y)  
#define rep(i,j,k) for (int i = j; i <= k; i++)  
#define per(i,j,k) for (int i = j; i >= k; i--)  
#define lson x << 1, l, mid  
#define rson x << 1 | 1, mid + 1, r  
const int lowbit(int x) { return x&-x; }  
const double eps = 1e-8;  
const int INF = 1e9+7; 
const ll inf =(1LL<<62) ;
const int MOD = 1e9 + 7;  
const ll mod = (1LL<<32);
const int N = 101010; 
template <class T1, class T2>inline void getmax(T1 &a, T2 b) { if (b>a)a = b; }  
template <class T1, class T2>inline void getmin(T1 &a, T2 b) { if (b<a)a = b; }
int read()
{
	int v = 0, f = 1;
	char c =getchar();
	while( c < 48 || 57 < c ){
		if(c=='-') f = -1;
		c = getchar();
	}
	while(48 <= c && c <= 57) 
		v = v*10+c-48, c = getchar();
	return v*f;
}
int n;
ll c[N];
string s1[N];
string s2[N];
ll dp[N][2];

int main() 
{
	#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif
    n=read();
    for (int i = 1; i <= n; i++) cin >> c[i];
    for (int i = 1; i <= n; i++) cin >> s1[i];
    for (int i = 1; i <= n; i++)
	{
        s2[i] = s1[i];
        reverse(s2[i].begin(),s2[i].end());
        
    }
    dp[1][0] = 0;
    dp[1][1] = c[1];
    for (int i = 2; i <= n; i++) 
	{
        dp[i][0] = inf;
        dp[i][1] = inf;
        if (s1[i-1] <= s1[i]) dp[i][0] = min(dp[i][0],dp[i-1][0]);
        if (s2[i-1] <= s1[i]) dp[i][0] = min(dp[i][0],dp[i-1][1]);
        if (s1[i-1] <= s2[i]) dp[i][1] = min(dp[i][1],dp[i-1][0]+c[i]);
        if (s2[i-1] <= s2[i]) dp[i][1] = min(dp[i][1],dp[i-1][1]+c[i]);
    }
    ll ans = min(dp[n][0],dp[n][1]);
    if (ans == inf) puts("-1");
    else printf("%I64d\n",ans);
}