图书管理员小P每天要整理书架,一个书架有N排,每一排书架上能摆放k本书,每本书上都有索引的数字编号,例如1,5,7等等。
小P喜欢从数字编号排列最整齐的书架开始整理,因为这样的话这排书架上的书就不用整理,按照整齐程度整理,最后整理最不整齐的那排书架。
那么能否请机智的你帮助小P找出整理书架的顺序呢?
整齐程度的定义:每排书架中书的编号存在的逆序对越少,这排书架就越整齐,一排书架中若书的编号完全升序即为最整洁。
逆序对的定义:在一个数组A中,在i < j的情况下,有A[i] > A[j],则(i,j)就称为数组A中的一个逆序对。
输入格式
第一行输入N,表示书架排数。
第二行输入k,表示每排书架上书的数量。
之后的N*k的数组表示每本书的数字编号。
输出格式
输出按照整齐程度,对各排书架重新排序后得到的新N*k的数组。
输出共一行,具体形式参考输出样例。
注意,逆序数相同则按书架原有顺序整理。
数据范围
1≤N,k≤2001≤N,k≤200,
1≤数字编号≤100001≤数字编号≤10000
输入样例:
4
8
0 1 2 3 4 5 6 7
11 6 5 7 3 2 2 0
2 3 6 1 9 3 5 4
0 2 4 5 3 10 6 7
输出样例:
[[0, 1, 2, 3, 4, 5, 6, 7], [0, 2, 4, 5, 3, 10, 6, 7], [2, 3, 6, 1, 9, 3, 5, 4], [11, 6, 5, 7, 3, 2, 2, 0]]
这道题目比较简单,但是代码量比较大,注意,这个题目一维数组的范围只有200,所以计算逆序数的时候只需要用O(N^2) 即可。
这里排序的时候的时候,要注意,不要将原来的数组封装到一个结构体里面排序,这样交换会比较费时(涉及到拷贝),可以封装一个指针。但比较麻烦。 这里直接开一个索引数组,表示一种下标映射关系。
排序的时候,使用稳定排序,这样就不需要额外处理当逆序数相同时的条件
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 200;
int nums[N][N];
int index[N]; // 索引数组
int Inversion[N]; // 存放每一排的逆序数
bool cmp(int a, int b) {
return Inversion[a] < Inversion[b];
}
int main()
{
int n, m;
cin >> n >> m;
for (int i = 0; i < n; i++) {
index[i] = i;
for (int j = 0; j < m; j++) {
cin >> nums[i][j];
}
for (int j = 0; j < m; j++) {
for (int k = j + 1; k < m; k++) {
if (nums[i][j] > nums[i][k])
Inversion[i]++;
}
}
}
stable_sort(index, index + n, cmp);
cout << '[';
for (int i = 0; i < n; i++)
{
cout << '[';
for (int j = 0; j < m; j++)
{
cout << nums[index[i]][j];
if (j != m - 1) cout << ", ";
}
cout << ']';
if (i != n - 1) cout << ", ";
}
cout << ']';
}