1050 螺旋矩阵 (25 分)
本题要求将给定的 N 个正整数按非递增的顺序,填入“螺旋矩阵”。所谓“螺旋矩阵”,是指从左上角第 1 个格子开始,按顺时针螺旋方向填充。要求矩阵的规模为 m 行 n 列,满足条件:m×n 等于 N;m≥n;且 m−n 取所有可能值中的最小值。
输入格式:
输入在第 1 行中给出一个正整数 N,第 2 行给出 N 个待填充的正整数。所有数字不超过 10
4
,相邻数字以空格分隔。
输出格式:
输出螺旋矩阵。每行 n 个数字,共 m 行。相邻数字以 1 个空格分隔,行末不得有多余空格。
输入样例:
12
37 76 20 98 76 42 53 95 60 81 58 93
输出样例:
98 95 93
42 37 81
53 20 76
58 60 76
解题思路:
1.划分行和列问题,从n的平方根向下找第一个能被n整除的数就是列数,行数=n/列数
2.将输入的数据排序(我是按照升序排列,取数据的时候从数组最后一个元素开始取)
3.最关键的部分,将数组的元素加入到螺旋矩阵中
如图:将矩阵按层划分,每一层分成四个小块(左->右,上->下,右->左,下->上 四个方向分别进行处理)
这样划的缺点,当行和列相等且都是奇数时,处理到最内层的时候就一个元素,这个时候要单独处理这个情况
解决办法如下图:将右边(上->下)小块长度增加1,下边(右->左)小块长度减少1(因为行数>=列数,所以选择纵向多处理一个数据),这样只需要一个大循环里面嵌四个小循环搞定,不需要单独处理特殊情况
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
int main()
{
int n, i, j;
cin >> n;
vector<int> arr(n);
for (i = 0; i<n; ++i)
cin >> arr[i];
sort(arr.begin(), arr.end());
int sq = sqrt(n);
int row, col;
while (n%sq)
--sq;
col = sq;
row = n / sq;
if (n == 0)
return 0;
int **matrix = new int*[row];
int count = arr.size() - 1;
for (i = 0; i<row; ++i)
{
matrix[i] = new int[col];
}
//将数组元素加入到螺旋矩阵中
int l;//层数
for (l = 0; l < col / 2 + 1; ++l)
{
//每一层开始下标 行=列=层号
for (i = j = l; j < col - l - 1 && count >= 0; ++j, --count)
matrix[i][j] = arr[count];
for (i = l; i <= row - l - 1 && count >= 0; ++i, --count)
matrix[i][j] = arr[count];
//从上往下的方向上比其他方向上多处理一个数据
//循环结束指向最后一行后面,会越界,所以要减一
--i;
for (j = col - l - 2; j >l&&count >= 0; --j, --count)
matrix[i][j] = arr[count];
for (i = row - l - 1; i >l && count >= 0; --i, --count)
matrix[i][j] = arr[count];
}
for (i = 0; i<row; ++i)
{
for (j = 0; j<col; ++j)
{
printf("%d", matrix[i][j]);
if (j<col - 1)
putchar(' ');
}
putchar('\n');
}
for (i = 0; i<row; ++i)
delete[]matrix[i];
delete[]matrix;
return 0;
}