1 条题解
-
0
重新理解一下题意,这两种操作其实可以把一个位置的元素向前移动 或 。
那既然如此,我们便将每个值 的位置移动到下标 即可,如果相距超过 就移动两个位置,否则移动 个。
for (int i = 1; i <= n - 2; i++) {//每次选择三个 int pos; for (int j = i; j <= n; j++) {//由于按顺序排放,i的位置一定>=i if (i == a[j]) { pos = j; break; } } if (i == pos) continue; while (pos - i >= 2) { mov2(pos);//左移2 pos -= 2; } if (pos != i) mov1(pos);//左移1 }但是这种情况由于要同时考虑三个下标,所以无法处理 和 。怎么办,特殊判断一下即可。
我们发现向前移动两个的话是不会改变其余位置的相对顺序的,但移动一个不一定。故如果第 个位置的元素可以通过两个两个移动到自己的位置上的话,我们就认为该情况可行,计入答案。否则就是无解。
换句话说,如果 和 不匹配, 还是奇数,就无解。
最后再将 移到最前面。
#include <bits/stdc++.h> #define ll long long using namespace std; const int N = 2100; int n, a[N], st; vector<pair<int, int> > ans; void mov(int id) {//将id位置转换为开头 if (id == st) return ; ans.push_back(make_pair((st - id + n) % n, 1)); st = id; } void mov1(int id) {//左移1 mov(id - 1); ans.push_back(make_pair(2, 2)); swap(a[id - 1], a[id]); swap(a[id + 1], a[id]); } void mov2(int id) {//左移2 mov(id - 2); ans.push_back(make_pair(1, 2)) ; swap(a[id - 1], a[id]); swap(a[id - 2], a[id - 1]); } int main() { scanf("%d", &n); st = 1;//现在开头的位置 for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); } if (n == 1) { printf("0"); return 0; } if (n == 2) { if (a[1] < a[2]) { printf("0"); } else { printf("1\n1a"); } return 0; } for (int i = 1; i <= n - 2; i++) {//每次选择三个 int pos; for (int j = i; j <= n; j++) {//由于按顺序排放,i的位置一定>=i if (i == a[j]) { pos = j; break; } } if (i == pos) continue; while (pos - i >= 2) { mov2(pos);//左移2 pos -= 2; } if (pos != i) mov1(pos);//左移1 } if (a[n - 1] == n) { if (n & 1) { printf("NIE DA SIE"); return 0; } int pos = n - 1; while (pos != 1) { mov2(pos); pos -= 2; } } int pos; for (int i = 1; i <= n; i++) { if (a[i] == 1) { pos = i; break; } } mov(pos); printf("%d\n", (int)ans.size()); for (auto v : ans) { if (v.second == 1) { printf("%da ", v.first); } else { printf("%db ", v.first); } } return 0; }
- 1
信息
- ID
- 3879
- 时间
- 400ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者