题目:这里
题意:给定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 }