E.小沙的印章
E.小沙的印章
题目描述
小沙在玩团队游戏,他的团队需要赢得比赛,小沙的团队包括小沙在内有 n 个人,每个人有一种与其他人不同的印章。他们围成一个环,分别编号为 1 , 2 , 3 ... n,一开始 x 与 x−1 和 x+1 相邻,特别的 1 与 n 相邻。在每轮游戏中,每个人可以和他相邻的其中一个人组成搭档,也可以不组。然后每对搭档交换位置。
除了交换位置的时候,在任何时候,每个人都可以给他相邻的人印上他的印章图案的印花,每个人的印章只能自己使用,不得传递。
你需要提出一种方案使得 n 轮内每个人收集全所有印花。每个人默认拥有自己印章的印花。
输入描述:
输入一个整数 n ,\(1\le n \le 10^3\)。
输出描述:
第一行输出一个整数 k ,代表总共交换的多少轮。
随后输出 k 轮,其中 \(0 \le k \le n\) 。
每轮第一个行一个整数 q 代表本轮交换多少对。
随后的 q 行,每行输出两个整数代表交换者的编号。
输入
4
输出
1
1
3 4
说明
一开始每个人能获得到的印花分别为:
1:1 2 4
2:1 2 3
3:2 3 4
4:1 3 4
当交换之后
1获得3
2获得4
3获得1
4获得2
所有人均获得所有印花。
思路点拨
-
难点在于构造。
-
题目没有要求最少或者最多,只要找到一种能达到要求的即可,思考冒泡排序的过程,针对一开始递增序列变为最后递减序列,整个过程的冒泡排序正好可以使得任何两项都会相遇。
-
有一个注意点,只能移动一对,也就是说冒泡排序,这一对交换了,必须让i += 2,不能用i+1去冒泡排序,i 和 i + 1已经交换过了,不能拿交换过的i + 1在和 i +2交换,不符合一对原则,不可以再去交换。
-
利用函数std::is_sorted(a.begin(),a.end(),std::greater
()),判断是否为递减序列,没有greater 作用是判断是否为递增序列。
提交代码
// Problem: 小沙の印章
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/46813/E
// Memory Limit: 524288 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
using i64 = long long;
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
std::cin >> n;
std::vector<int> a(n);
std::iota(a.begin(), a.end(),1);
std::vector< std::vector<std::pair<int,int> > > ans;
while(!std::is_sorted(a.begin(),a.end(),std::greater<int>()))
{
std::vector<std::pair<int,int> > s;
for(int i = 1; i < n; i++)
{
if(a[i] > a[i - 1])
{
std::swap(a[i], a[i - 1]);
s.emplace_back(a[i], a[i - 1]);
i++;
}
}
ans.push_back(s);
}
std::cout << ans.size() << "\n";
for(auto v : ans)
{
std::cout << v.size() << "\n";
for(auto item : v)
{
std::cout << item.first << " " << item.second << "\n";
}
}
return 0;
}

浙公网安备 33010602011771号