CodeForces 706C-Hard problem(基本的DP)

原创 2016年08月31日 10:42:27

题目链接:http://codeforces.com/problemset/problem/706/C
题目大意:
输入一个正整数n,再输入一个长度为n的数组c[0…n-1]和n个字符串。
已知把第i个字符串翻转需要的能量为c[i],求把n个字符串通过翻转操作变成字典序所需最小能量,若不能实现则输出-1。

题目分析:
这是一个最优决策的问题,而且容易知道,排第i个字符串时,必须保证前i-1个字符串都有可能通过翻转操作成为字典序,否则无解,也满足最优子问题的特性,所以考虑DP。

设dp[i][0]表示前i个字符串已经排好,最后一个字符串没翻转,dp[i][1]表示前i个字符串已经排好,最后一个字符串翻转。然后转移一下就好了,我也写不太好转移方程。。。。

反正dp[i][0]有三种取值,dp[i-1][0],dp[i-1][1],-1.分别考虑s[i]与s[i-1]和rev[i-1]的关系即可。
dp[i][1]也有三种取值,dp[i-1][0]+c[i],dp[i-1][1]+c[i],-1,同理取决于rev[i]和s[i-1]、rev[i-1]的关系。

这题还有一个坑就是,因为c[i]的范围最大可以到1e9,数组又有1e5的长度,所以理论上最大值有可能到1e14,答案要写long long。
有一个注意的地方就是C++的string可以直接用大于号、小于号比较字典序。而C不行,需要调用strcmp.好像Python也可以这么搞吧。。。。

AC代码:

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int c[100005];
ll dp[100005][2];
string s[100005],rev[100005];
int main() {
  int n;
  scanf("%d", &n);
  for(int i=0;i<n;i++)
    scanf("%d", &c[i]);
  for(int i=0;i<n;i++) {
    cin>>s[i];
    rev[i]=s[i];
    reverse(rev[i].begin(),rev[i].end());
  }

  memset(dp,-1,sizeof(dp));
  dp[0][0]=0;dp[0][1]=c[0];
  for(int i=1;i<n;i++) {
    if(s[i]>=s[i-1] && dp[i-1][0]!=-1)
      dp[i][0]=dp[i-1][0];
    if(s[i]>=rev[i-1] && dp[i-1][1]!=-1) {
      if(dp[i][0]!=-1)
        dp[i][0]=min(dp[i][0],dp[i-1][1]);
      else
        dp[i][0]=dp[i-1][1];
    }

    if(rev[i]>=s[i-1] && dp[i-1][0]!=-1)
      dp[i][1]=dp[i-1][0]+c[i];
    if(rev[i]>=rev[i-1] && dp[i-1][1]!=-1) {
      if(dp[i][1]!=-1)
        dp[i][1]=min(dp[i][1],dp[i-1][1]+c[i]);
      else
        dp[i][1]=dp[i-1][1]+c[i];
    }
  }

  for(int i=0;i<n;i++) {
    cout<<dp[i][0]<<','<<dp[i][1]<<endl;
  }
  if(dp[n-1][0]==-1 && dp[n-1][1]==-1)
    printf("-1\n");
  else if(dp[n-1][0]!=-1 && dp[n-1][1]!=-1)
    printf("%I64d\n", min(dp[n-1][0],dp[n-1][1]));
  else if(dp[n-1][0]==-1)
    printf("%I64d\n", dp[n-1][1]);
  else
    printf("%I64d\n", dp[n-1][0]);

}
版权声明:完整版Leetcode题解请出门左转https://github.com/cmershen1/leetcode/tree/master/docs

相关文章推荐

CodeForces 706C Hard problem【dp】

Description Vasiliy is fond of solving different tasks. Today he found one he wasn't able to solve ...
  • Bcwan_
  • Bcwan_
  • 2016年10月19日 01:46
  • 99

Hard problem CodeForces - 706C (DP)

Vasiliy is fond of solving different tasks. Today he found one he wasn't able to solve himself, so h...

codeforces 706 C. Hard problem #367 div2

顺序给出 n 个字符串,不能交换顺序,但每个串都可以反转(reverse),代价为 ci,问能不能使得这些字符串从前往后字典序是从小到大的,并算出最小代价 dp[2][n] 记录代价,dp[0][] ...

Codeforces-706C Hard problem

题目大意: 给你n个字符串,让你把它排序成字典序,但是任何两个字符串之间不能交换,只能对每个字符串进行翻转操作,并且第i个字符串翻转的时候,会消耗c[i]的能量,然后问你,将这些字符串排成字典序的时...
  • Snow_Me
  • Snow_Me
  • 2016年08月12日 14:37
  • 385

codeforces706C Hard problem 动态规划

C. Hard problem time limit per test 1 second memory limit per test 256 megabytes in...

【Codeforces 706C . Hard problem】

. Hard problem. Hard problem time limit per test1 second memory limit per test256 megabytes input...

codeforces 706C Hard problem

Vasiliy is fond of solving different tasks. Today he found one he wasn't able to solve himself, so h...

【动态规划】Codeforces 706C Hard problem

题目链接:   http://codeforces.com/contest/706/problem/C 题目大意:   n(2 ≤ n ≤ 100 000)个字符串(长度不超过100000),翻转费用...

cf 706C Hard Problem(dp)

> C. Hard problem time limit per test 1 second memory limit per test 256 megabytes ...

codefoces 706C Hard problem (dp/dfs)

C. Hard problem http://codeforces.com/problemset/problem/706/C Vasiliy is fond of solving differen...
  • wchhlbt
  • wchhlbt
  • 2016年08月12日 20:16
  • 119
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:CodeForces 706C-Hard problem(基本的DP)
举报原因:
原因补充:

(最多只允许输入30个字)