题目大意:
将给定的N个正整数按非递增的顺序,填入螺旋矩阵,所螺旋矩阵,就是从左上第一个给开始,按顺时针方向填充。要求矩阵的规模为m行n列。
满足条件,m*n等于N,m>=n,取m-n中最小值。
思路:
1)题目要求按非递增的顺序,因此先对数组排序,从大到小。
2)m与n的确定,m与n一定是N的约数,且m>=n,所以m必须是不小于sqrt(N)的最小整数,因此让m从sqrt(N)向上递增,直到N%m==0,此时n=N/m。
3)对螺旋矩阵的赋值以圈为单位进行,即每次先填完外面一圈逐渐向里面的圈填,直到填充个数等于N,设置上下左右四个边界,UDLR。对每一层,从左上角开始填,先向右,到达右边界,再向下,达到下边界,再向左,到达左边界,再向上,到达上边界。至此填完一圈,UDLR各减一,(向里进一层)依次类推。指针重新定位到里面一层的左上角。
4)当N是完全平方数时最里面一层只有一个数,需要特判。N如果是素数,只有一列,此时行数为N,列数最多sqrt(N)。
AC代码:
//PAT_A 1105
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn = 10010;
int matrix[maxn][maxn], A[maxn];
bool cmp(int a, int b) {
return a > b;
}
int main() {
int N, m, n;
(void)scanf("%d", &N);
for (int i = 0; i < N; i++) {
(void)scanf("%d", &A[i]);
}
if (N == 1) {
printf("%d", A[0]);
return 0;
}
sort(A, A + N, cmp);
m = (int)ceil(sqrt(1.0 * N));
while (N % m != 0)m++;
n = N / m;
int u = 1, d = m, l = 1, r = n;//边界
int i = 1, j = 1, now = 0;
while (now < N) {
while (now < N && j < r) {//向右
matrix[i][j] = A[now++];
j++;
}
while (now < N && i < d) {//向下
matrix[i][j] = A[now++];
i++;
}
while (now < N && j > l) {//向左
matrix[i][j] = A[now++];
j--;
}
while (now < N && i > u) {//向上
matrix[i][j] = A[now++];
i--;
}
i++; j++; u++; d--; l++; r--;//缩小边界,移动指针
if (now == N - 1)matrix[i][j] = A[now++];
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
printf("%d", matrix[i][j]);
if (j < n)printf(" ");
else printf("\n");
}
}
return 0;
}