1050 螺旋矩阵(25)(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
分析:得到了m和n之后,根据m和n的值确定填充的边界,按照先向右再向下再向左再向下的顺序,从最外面一圈一圈地填充螺旋矩阵。将所有的数据填充到螺旋矩阵中需要顺时针绕的圈数为m和n中较小的那个除以2向上取整,例如,5行3列(5行3列也一样),3 / 2 = 1.5, 向上取整后为2,需要绕两圈。由于ceil()函数返回值为double,强转为int会失真,所以用(int)min(m, n) + 1) / 2进行圈数的计算。注意,当填充了若干圈后,若只剩下一列没有填充,这个时候就不可以再向上填充了。
代码:
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
bool cmp(int a, int b) {return a > b;}
int main()
{
int i, j, N, m, n;
scanf("%d", &N);
for(i = ceil(sqrt(N)); i <= N; i++)
if(N % i == 0)
{ //得到m和n
m = i;
n = N / m;
break;
}
int in[m][n];//输入的数
int out[m][n];//螺旋矩阵
int circle = 0;//记录正在填充第几圈
int order = 0;//记录正在填充第几个数字
for(i = 0; i < N; i++)
scanf("%d", in[0] + i);
sort(in[0], in[0] + N, cmp);
while(circle < ((int)min(m, n) + 1) / 2)
{ //
//i控制行数,j控制列数
i = circle;//每一圈的起始行数,起始列数在for循环中初始化
for(j = circle; j < n - circle; j++)
{ //向右填充
out[i][j] = *(in[0] + order);
order++;
}
for(j--, i += 1; i < m - circle; i++)
{ //向下填充
out[i][j] = *(in[0] + order);
order++;
}
for(i--, j -= 1; j >= circle; j--)
{ //向左填充
out[i][j] = *(in[0] + order);
order++;
}
//向上填充
if(n - circle * 2 > 1)//只有1列的话不需要向上填充
for(j++, i -= 1; i > circle; i--)
{
out[i][j] = *(in[0] + order);
order++;
}
circle++;
}
for(i = 0; i < m; i++)
{ //输出螺旋矩阵
for(j = 0; j < n; j++)
{
printf("%d", out[i][j]);
if(j != n - 1)
printf(" ");
}
printf("\n");
}
return 0;
}