您的位置:首页 > 其它

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

2016-09-09 17:15 375 查看
题目链接:

http://codeforces.com/contest/706/problem/C

分析:

给出n个字符串和把每个字符串翻转所需要的费用Ci,每个字符串都可以选择翻转或者不翻转,求将n个字符串变成字典序所需要的最小费用,若不能变成字典序则输出-1.

字典序: 若在字典序上A在B前面则A是B的前缀 或者 A和B第一个不相同的字符是A[i]<B[i]。

题解:

设dp[i][1]/[0] 表示第i个字符串翻转/不翻转时构成字典序的最小cost。

初始化: dp[1][0] = 0, dp[1][1] = cost[1];

(str[i]表示第i个字符串, ~str[i]表示第i个字符串翻转)

第一个判断:

str[i] > str[i-1] && str[i]> ~str[i-1] dp[i][0] = min(dp[i][0], min(dp[i-1][0], dp[i-1][1]) );

str[i] > str[i-1] && str[i]< ~str[i-1] dp[i][0] = min(dp[i][0], dp[i-1][0]);

str[i] < str[i-1] && str[i]> ~str[i-1] dp[i][0] = min(dp[i][0], dp[i-1][1]);

str[i] < str[i-1] && str[i]< ~str[i-1] dp]i][0] = INF;

第二个判断:

~str[i] > str[i-1] && str[i]> ~str[i-1] dp[i][1] = min(dp[i][1], min(dp[i-1][0], dp[i-1][1])+cost[i] );

~str[i] > str[i-1] && str[i]< ~str[i-1] dp[i][1] = min(dp[i][1], dp[i-1][0]+cost[i] );

~str[i] < str[i-1] && str[i]> ~str[i-1] dp[i][1] = min(dp[i][1], dp[i-1][1]+cost[i] );

~str[i] < str[i-1] && str[i]< ~str[i-1] dp]i][1] = INF;

AC代码:



/*************************************************************************
> File Name: test.cpp
> Author: Akira
> Mail: qaq.febr2.qaq@gmail.com
************************************************************************/

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <set>
#include <list>
#include <ctime>
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define Sqr(a) ((a)*(a))
using namespace std;

#define MaxN 100005
#define MaxM MaxN*10
#define INF (LL)1e15
#define bug cout<<88888888<<endl;
int n;
LL cost[MaxN];

string str[MaxN];
string Rstr[MaxN];

LL dp[MaxN][2];

string Re(string str)
{
string s;
for(int i=str.length()-1;i>=0;i--)
{
s+=str[i];
}
return s;
}

bool judge(string a, string b)
{
if(a==b) return true;

int alen = a.length();
int blen = b.length();
if(alen > blen)
{
int i=0;
while(a[i]==b[i] && i<blen) i++;
if(i>=blen) return true;
if( a[i]>b[i] ) return true;
else  return false;
}
else
{
int i=0;
while(a[i]==b[i] && i<alen) i++;
if(i>=alen) return false;
if( a[i]>b[i] ) return true;
else  return false;
}
}

void solve()
{
for(int i=1;i<=n;i++)
{
Rstr[i] = Re(str[i]);
//cout << Rstr[i] << endl;
}
for(int i=1;i<=n;i++)
{
dp[i][0]=INF;
dp[i][1]=INF;
//cout << dp[i][1] << endl;
}
dp[1][0] = 0;
dp[1][1] = cost[1];

for(int i=2;i<=n;i++)
{
int flag0 = judge(str[i], str[i-1]);
int flag1 = judge(str[i], Rstr[i-1]);
//cout << flag0 << " " << flag1 << endl;
if( flag0 && flag1 ) dp[i][0] = min(dp[i][0], min(dp[i-1][0], dp[i-1][1]) );
if( flag0 && !flag1 ) dp[i][0] = min(dp[i][0], dp[i-1][0]);
if( !flag0 && flag1 ) dp[i][0] = min(dp[i][0], dp[i-1][1]);
if( !flag0 && !flag1 ) dp[i][0] = INF;

flag0 = judge(Rstr[i], str[i-1]);
flag1 = judge(Rstr[i], Rstr[i-1]);
if( flag0 && flag1 ) dp[i][1] = min(dp[i][1], min(dp[i-1][0], dp[i-1][1])+cost[i] );
if( flag0 && !flag1 ) dp[i][1] = min(dp[i][1], dp[i-1][0]+cost[i] );
if( !flag0 && flag1 ) dp[i][1] = min(dp[i][1], dp[i-1][1]+cost[i] );
if( !flag0 && !flag1 ) dp[i][1] = INF;
//cout << flag0 << " " << flag1 << endl;

//cout << dp[i][0] << " " << dp[i][1] << endl;
}
}

int main()
{
while(~scanf("%d", &n))
{
for(int i=1;i<=n;i++)
scanf("%I64d", &cost[i]);

for(int i=1;i<=n;i++)
{
cin >> str[i];
}

solve();
LL ans = min(dp
[0], dp
[1]);

if(ans >= INF) cout << -1 << endl;
else cout << ans << endl;
}

//system("pause");
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp codeforces