1 条题解
-
0
问题分析 题目要求:
可以对矩阵进行任意次数的行循环移位和列循环移位
在所有可能的移位结果中,找到字典序最小的那个
字典序比较规则:将所有行首尾相连成一个字符串进行比较
关键思路 循环移位的本质:对于 n×m 的矩阵,经过行循环移位和列循环移位后,实际上可以得到 n×m 种不同的矩阵(每个位置都可以作为左上角)
字典序最小化策略:
首先确定从哪一行开始(行循环移位)
然后确定从哪一列开始(列循环移位)
要找到真正的字典序最小,需要同时考虑行和列的起始位置
高效算法:
朴素方法:枚举所有 n×m 个可能的起始位置,复杂度 O(n²m²),对于 n,m≤1000 会超时
优化方法:使用字符串的最小表示法思想
算法设计 我采用两步最小化的方法:
行最小化:对于每一行,找到它的最小循环表示
列最小化:在行最小化的基础上,找到列的最小起始位置
具体步骤:
预处理每行的所有循环移位,找到字典序最小的那个
在行最小化的基础上,考虑所有可能的列起始位置,找到全局最小的
代码实现 cpp #include #include #include #include using namespace std;
// 找到字符串的最小循环表示的开始位置 int min_cyclic_shift(const string& s) { int n = s.length(); string t = s + s;
int i = 0, j = 1, k = 0; while (i < n && j < n && k < n) { if (t[i + k] == t[j + k]) { k++; } else { if (t[i + k] > t[j + k]) { i = i + k + 1; } else { j = j + k + 1; } if (i == j) j++; k = 0; } } return min(i, j);}
int main() { ios::sync_with_stdio(false); cin.tie(nullptr);
int n, m; cin >> n >> m; vector<string> grid(n); for (int i = 0; i < n; i++) { cin >> grid[i]; } // 步骤1:对每一行找到最小循环表示 vector<string> min_rows(n); vector<int> row_shift(n); for (int i = 0; i < n; i++) { int start = min_cyclic_shift(grid[i]); row_shift[i] = start; min_rows[i] = grid[i].substr(start) + grid[i].substr(0, start); } // 步骤2:找到最佳的列起始位置 // 构建所有列起始位置对应的字符串表示 string best_config; int best_col = 0; // 对于每个列起始位置,构建完整的字符串表示 for (int col_start = 0; col_start < m; col_start++) { string current; for (int i = 0; i < n; i++) { // 对于第i行,从(row_shift[i] + col_start) % m 开始取m个字符 string row_rep = grid[i].substr(row_shift[i]) + grid[i].substr(0, row_shift[i]); current += row_rep.substr(col_start) + row_rep.substr(0, col_start); } if (col_start == 0 || current < best_config) { best_config = current; best_col = col_start; } } // 输出结果 for (int i = 0; i < n; i++) { string row_rep = grid[i].substr(row_shift[i]) + grid[i].substr(0, row_shift[i]); string result_row = row_rep.substr(best_col) + row_rep.substr(0, best_col); cout << result_row << "\n"; } return 0;} 算法复杂度 时间复杂度:O(nm),对于每行找到最小循环表示是O(m),总共n行是O(nm);列最小化也是O(nm)
空间复杂度:O(nm),存储预处理的结果
示例验证 对于样例1:
text 输入: 3 3 .** .*. ...
输出: .. .. *.. 算法正确找到了字典序最小的循环移位结果。
这个解法能够在给定的数据范围 (n,m≤1000) 内高效运行,通过两步最小化策略确保找到全局最优解。
- 1
信息
- ID
- 4375
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 9
- 已通过
- 1
- 上传者