标签:cpp += tchar push ati ++ git 比赛 print
由题意易得每列互不相关,对每列单独考虑
在一列中,有些数本来就是目标状态中这一列的数,可以通过若干次移动操作使其在正确的位置,有些数则只能修改
统计这一列如果移动 k 次(0 <= k <= n - 1)有多少数不需要修改
设第 i 行第 j 列的数为 x,若 x <= n * m && (x - j) % m == 0, 说明 x 在目标状态中是第 j 列第 (x - j) / m + 1 行的数,(注意这里一定要判断x <= n * m,比赛时没判断查了半天也没发现)
可以通过 p = (i - (x - j) / m - 1 + n) % n 次移动操作使 x 在正确的位置(+ n 在 % n 是为了处理负数)并在计数数组 c 中使 c[p]++
最后枚举移动次数 k,这一列需要的步骤 ans = min (k + n - c[k]),并将 ans 累加到最终答案res中
#include <bits/stdc++.h>
using namespace std;
inline void read (int &x) {
char ch = getchar(); x = 0;
while (!isdigit(ch)) ch = getchar();
while (isdigit(ch)) x = x * 10 + ch - 48, ch = getchar();
}
const int N = 2e5 + 10;
int n, m, res, c[N];
vector<int> v[N];
signed main() {
read (n), read (m);
int x;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j) read (x), v[i].push_back (x);
for (int j = 1; j <= m; ++j) {
for (int i = 0; i < n; ++i) c[i] = 0;
int ans = 1e9, tmp = 0;
for (int i = 1; i <= n; ++i) {
int t = v[i][j - 1];
if ((t - j) % m == 0 && t <= n * m)
++c[(i - (t - j) / m - 1 + n) % n];
}
for (int i = 0; i < n; ++i) ans = min (ans, i + n - c[i]);
res += ans;
} printf ("%d\n", res);
return 0;
}
CF1294E Obtain a Permutation 题解
标签:cpp += tchar push ati ++ git 比赛 print
原文地址:https://www.cnblogs.com/whx666/p/12230325.html