CF367C. Hard problem

链接[http://codeforces.com/group/1EzrFFyOc0/contest/706/problem/C]

题意:

他希望它们按词典顺序排序(就像字典中那样),但他不允许交换其中的任何一个。
唯一允许他做的操作是将其中的任何一个反转(第一个字符变成最后一个,
第二个字符变成最后一个,以此类推)。

思路;

DP,不断更新花费的值,并且判断是否可以满足字典序排序。
dp[i][0]表示,表示排到第i+1个字符串,不需要反转需要的花费,dp[i][0]表示排到第i+1个字符串,需要反转需要的花费。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
string reverse(string s)
{
	string res=s;
	int i,len=res.length();
	for(i=0;i<len/2;++i)
		swap(res[i],res[len-1-i]);
	return res;
}
string s[100005][2];//二维字符串数组 
ll dp[100005][2];
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	
	//map<string,int> m;
	int n,i;
	ll a[100005];
	//freopen("in.txt","r",stdin);
  while(cin>>n){
  	 for(i=0;i<n;i++)
  	cin>>a[i];
  	for(i=0;i<n;++i)
			dp[i][0]=dp[i][1]=9999999999999999;
  	dp[0][0]=0,dp[0][1]=a[0];
  	   for(i=0;i<n;++i)
		{
			cin>>s[i][0];
			s[i][1]=reverse(s[i][0]);
		}
  	for(i=1;i<n;i++)
  	{
  		if(s[i][0]>=s[i-1][0])
  		dp[i][0]=dp[i-1][0];//二者都不需要反转 
  		if(s[i][1]>=s[i-1][0])
  		dp[i][1]=dp[i-1][0]+a[i];//后者需要反转就dp[i-1][0]+a[i]
  		if(s[i][0]>=s[i-1][1])
  		dp[i][0]=min(dp[i][0],dp[i-1][1]);//前者需要反转,因为开始初始化一个很大的数所以要比较 
  		if(s[i][1]>=s[i-1][1])
  		dp[i][1]=min(dp[i][1],dp[i-1][1]+a[i]);//二者都需要反转,且初始化为很大,需要比较 
  		if(dp[i][0]==9999999999999999&&dp[i][1]==9999999999999999)
		  //如果不满足字典序排序,就退出DP 
  		break;
	  }
	  ll ans=min(dp[n-1][0],dp[n-1][1]);
	  if(i>=n) cout<<ans<<endl;
	  else cout<<-1<<endl;
  }
	return 0;
}
posted @ 2018-08-08 14:13  ChunhaoMo  阅读(1058)  评论(0编辑  收藏  举报