1 条题解
-
0
解题思路
我们将使用动态规划来解决这个问题。定义 为使得前 个字符串按字典序排序,且第 个字符串在以下状态时所需的最小能量:
- :第 个字符串未反转;
- :第 个字符串已反转。
状态 可由 和 转移而来。在转移时,需要检查第 个字符串是否字典序大于或等于第 个字符串:
- 如果 ,应检查反转后的第 个字符串;
- 对第 个字符串同理(根据 或 对应的状态选择原始或反转后的字符串)。
转移方程为:
- $dp[i][j] = \min(dp[i][j],\ dp[i-1][0] + j \cdot c[i])$ (当第 个字符串未反转且满足字典序条件时)
- $dp[i][j] = \min(dp[i][j],\ dp[i-1][1] + j \cdot c[i])$ (当第 个字符串已反转且满足字典序条件时)
最终答案为 。
时间复杂度:。
C++ 代码实现
#include <bits/stdc++.h> using namespace std; using ll = long long; const ll INF = 1e18; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; vector<ll> c(n); for (int i = 0; i < n; ++i) { cin >> c[i]; } vector<string> s(n); for (int i = 0; i < n; ++i) { cin >> s[i]; } vector<string> rev(n); for (int i = 0; i < n; ++i) { rev[i] = s[i]; reverse(rev[i].begin(), rev[i].end()); } vector<vector<ll>> dp(n, vector<ll>(2, INF)); dp[0][0] = 0; dp[0][1] = c[0]; for (int i = 1; i < n; ++i) { // 当前不反转 if (s[i] >= s[i - 1]) { dp[i][0] = min(dp[i][0], dp[i - 1][0]); } if (s[i] >= rev[i - 1]) { dp[i][0] = min(dp[i][0], dp[i - 1][1]); } // 当前反转 if (rev[i] >= s[i - 1]) { dp[i][1] = min(dp[i][1], dp[i - 1][0] + c[i]); } if (rev[i] >= rev[i - 1]) { dp[i][1] = min(dp[i][1], dp[i - 1][1] + c[i]); } } ll ans = min(dp[n - 1][0], dp[n - 1][1]); if (ans >= INF) { cout << -1 << '\n'; } else { cout << ans << '\n'; } return 0; }
- 1
信息
- ID
- 6879
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者