官方题解|使两方格相等的最少操作次数
2024-03-22 11:42:19
发布于:浙江
12阅读
0回复
0点赞
题目解析
方格 的状态可以用 来表示,其中 是代表 行 原始位置的排列,而 是代表 列 原始位置的排列。
一开始 ;交换相邻的行或列相当于交换 或 中相邻的两个元素。
另外,当前方格中 上的整数可以从 的初始状态的 上的整数获得。
例如,对于题目中第一个样例转换的过程,状态 变化为
的总数是 的排列的数量和 的排列的数量的乘积即 。
因此,我们对这 个 ,即 的排列 和 的排列 中的每一个,执行以下操作:
- 首先,根据当前的 和 构造方格 并判断和方格 是否相等。
- 如果相等,求从初始状态到达当前 的最小操作次数。
如果没有任意一对 和 构造出的方格 与方格 相同,那么就不可能使方格 和方格 相等,输出 。
从初始状态到达当前状态 所需的最小操作数是以下操作之和:
- 通过重复交换相邻元素从初始序列 得到排列 所需的最少操作次数;
- 通过重复交换相邻元素从初始序列 得到排列 所需的最小操作次数;
从排列 开始,通过重复交换相邻的两个元素得到所需的排列 所需的运算次数为排列 中的 逆序对 的数量,即
- , 的 的个数。
因此,从初始状态到 所需的操作次数就是 的 逆序对 的数量与 的 逆序对 的数量之和。
AC代码
#include <bits/stdc++.h>
using namespace std;
int count(vector<int> &a) {
int n = a.size(), res = 0;
for (int i = 0; i < n; ++i)
for (int j = i + 1; j < n; ++j)
if (a[i] > a[j]) ++res;
return res;
}
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int _; cin >> _;
while (_--) {
int n, m;
cin >> n >> m;
vector<vector<int>> a(n, vector<int>(m));
vector<vector<int>> b(n, vector<int>(m));
for (auto &row : a)
for (auto &x : row) cin >> x;
for (auto &row : b)
for (auto &x : row) cin >> x;
vector<int> row(n), col(m);
iota(begin(row), end(row), 0);
iota(begin(col), end(col), 0);
int res = 100;
do {
do {
vector<vector<int>> c(n, vector<int>(m));
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
c[i][j] = a[row[i]][col[j]];
if (c != b) continue;
res = min(res, count(row) + count(col));
} while (next_permutation(begin(col), end(col)));
} while (next_permutation(begin(row), end(row)));
cout << (res < 100 ? res : -1) << '\n';
}
return 0;
}
复杂度分析
枚举所有的 时间复杂度为 ;
构造方格 并判断是否和 相等的时间复杂度为 ;
求 的逆序对数量时间复杂度为 ;
求 的逆序对数量时间复杂度为 ;
因此总的时间复杂度为 。
这里空空如也
有帮助,赞一个