题目:这里

题意:给定n个字符串,每个字符串可以进行一项操作,就是将这个字符串交换,就是该字符串的第一个和最后一个交换,第二个和倒数第二个交换,以此类推,当然可以选择对于

该字符串进行或不进行这项操作,而每个字符串都有一个相应的能量值,进行操作了就要消耗那么多能量值,最后是否能在消耗的能量值最小的情况下保证这些字符串是升序的(

字典序从小到大),不能就输出-1。

 

字符串用string,DP,dp[i][j]表示到第i个字符串的状态为j的时候(j为1表示这个串交换了,j为0表示这个串没有交换),注意的是不能形成升序的判断,并不是任意相邻的两个字符串

能够满足升序就可以了,还要考虑前面的。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<string>
 7 using namespace std;
 8 
 9 typedef long long ll;
10 #define inf 0x3f3f3f3f3f3f
11 const int M = 1e5 + 10;
12 ll v[M],dp[M][2];
13 string str[M];
14 
15 string revers(string x)
16 {
17     string y=x;
18     int len=x.length();
19     for (int i=0 ; i<len/2 ; i++)
20         swap(y[i],y[len-i-1]);
21     return y;
22 }
23 
24 ll min(ll x,ll y) {return x<y?x:y;}
25 
26 int main()
27 {
28     int n;
29     scanf("%d",&n);
30     for (int i=1 ; i<=n ; i++) {
31         scanf("%I64d",&v[i]);
32         dp[i][0]=dp[i][1]=inf;
33     }
34     for (int i=1 ; i<=n ; i++) cin>>str[i];
35     dp[1][0]=0;dp[1][1]=v[1];
36     bool flag1=false;int i;
37     for (i=2 ; i<=n ; i++)
38     {
39         bool flag2=false;
40         if (str[i]>=str[i-1])
41             dp[i][0]=dp[i-1][0],flag2=true;
42         if (str[i]>=revers(str[i-1]))
43             dp[i][0]=min(dp[i][0],dp[i-1][1]),flag2=true;
44         if (revers(str[i])>=str[i-1])
45             dp[i][1]=dp[i-1][0]+v[i],flag2=true;
46         if (revers(str[i])>=revers(str[i-1]))
47             dp[i][1]=min(dp[i][1],dp[i-1][1]+v[i]),flag2=true;
48         //if (!flag2) {flag1=true;break;}
49         if(dp[i][1]==inf&&dp[i][0]==inf)
50                 break;
51     }
52     //if (flag1) puts("-1");
53     if (i!=n+1)puts("-1");
54     else printf("%I64d\n",min(dp[n][1],dp[n][0]));
55     return 0;
56 }

 

posted on 2016-08-12 19:55  蜘蛛侦探  阅读(287)  评论(0编辑  收藏  举报