题目大意:
给你n个字符串,让你把它排序成字典序,但是任何两个字符串之间不能交换,只能对每个字符串进行翻转操作,并且第i个字符串翻转的时候,会消耗c[i]的能量,然后问你,将这些字符串排成字典序的时候产生的最小能量。如果不能排成字典序则输出-1
解题思路:
明显是个DP,对于每个字符串只有两个选择,翻转和不翻转,搜索的话是2^100000复杂度明显搞笑。亦可赛艇
DP做,就是与前面一个字符串进行比较
可以设dp[i][j]表示第j个字符串为i状态时所消耗的最小能量。i只为0和1
那么状态转移方程就很明显了。不知道状态转移的可以自己小推一下。
代码:
#include <cmath> #include <string> #include <iomanip> #include <iostream> #include <algorithm> using namespace std; //#define DEBUG 1 const int maxn = 100005; const long long INF = 1e16; string tmp, str[2][maxn]; long long c[maxn], dp[2][maxn]; int main() { int n; cin >> n; for (int i = 0; i < n; ++i) cin >> c[i]; for (int i = 0; i < n; ++i) { cin >> str[0][i]; tmp = str[0][i]; reverse(tmp.begin(), tmp.end()); str[1][i] = tmp; } dp[0][0] = 0; dp[1][0] = c[0]; for (int i = 1; i < n; ++i) { int flag = 0; dp[0][i] = dp[1][i] = INF; if (str[0][i] >= str[0][i - 1] && dp[0][i-1] != -1) { dp[0][i] = dp[0][i - 1]; flag = 1; } if (str[0][i] >= str[1][i - 1] && dp[1][i-1] != -1) { dp[0][i] = min(dp[0][i], dp[1][i-1]); flag = 1; } if (!flag) dp[0][i] = -1; flag = 0; if (str[1][i] >= str[0][i - 1] && dp[0][i - 1] != -1) { dp[1][i] = dp[0][i - 1] + c[i]; flag = 1; } if (str[1][i] >= str[1][i - 1] && dp[1][i - 1] != -1) { dp[1][i] = min(dp[1][i], dp[1][i-1] + c[i]); flag = 1; } if (!flag) dp[1][i] = -1; } if (dp[0][n - 1] == -1 && dp[1][n - 1] == -1) { cout << "-1" << endl; } else if (dp[0][n - 1] == -1) { cout << dp[1][n - 1] << endl; } else if (dp[1][n - 1] == -1) { cout << dp[0][n - 1] << endl; } else { cout << min(dp[0][n - 1], dp[1][n - 1]) << endl; } #ifdef DEBUG system("pause"); #endif // DEBUG return 0; }