C. Hard problem (dp)

  • 题目链接:http://codeforces.com/contest/706/problem/C
  • 题意:要使n个字符串变为字典序。只能进行一种操作:将第i个字符串reverse,并消耗c[i]的能量。求消耗的最小的能量
  • 算法:数据量100000,时限1s,只能用dp
  • 思路:
    • 状态:dp[i][j]表示前i个字符串变为字典序所消耗的最小能量。j==0时表示第i个字符串不反转,j==1时表示第i个字符串反转。
    • 转移:dp[i][j] = min( dp[i][j], dp[i-1][0] + c[i]*j), dp[i][j] = min(dp[i][j], dp[i-1][1] + c[i]*j);

#include <bits/stdc++.h>
#define pi acos(-1)
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;
const LL LL_INF = 0x3f3f3f3f3f3f3f3f;
const int maxn = 3e5 + 10;
const int mod = 1e9 + 7;

int c[maxn];
string s[maxn], tmp, pre;
LL dp[maxn][5];

int main()
{
    memset(dp, LL_INF, sizeof(dp));
    fastio;
    int n; cin >> n;
    for(int i=0; i<n; i++){
        cin >> c[i];
    }
    for(int i=0; i<n; i++){
        cin >> s[i];
    }
    dp[0][0] = 0;
    dp[0][1] = c[0];
    tmp = s[0];
    reverse(tmp.begin(), tmp.end());
    pre = tmp;
    for(int i=1; i<n; i++){
        tmp = s[i];
        reverse(tmp.begin(), tmp.end());
        if(s[i] >= s[i-1]){
            dp[i][0] = min(dp[i][0], dp[i-1][0]);
        }
        if(s[i] >= pre){
            dp[i][0] = min(dp[i][0], dp[i-1][1]);
        }
        if(tmp >= s[i-1]){
            dp[i][1] = min(dp[i][1], dp[i-1][0]+c[i]);
        }
        if(tmp >= pre){
            dp[i][1] = min(dp[i][1], dp[i-1][1]+c[i]);
        }

        pre = tmp;
    }
    LL ans = min(dp[n-1][0],dp[n-1][1]);
    if(ans >= LL_INF) cout << "-1" << endl;
    else  cout << ans << endl;
}

猜你喜欢

转载自blog.csdn.net/qq_37352710/article/details/81220637