本题要求将给定的N个正整数按非递增的顺序,填入“螺旋矩阵”。所谓“螺旋矩阵”,是指从左上角第1个格子开始,按顺时针螺旋方向填充。要求矩阵的规模为m行n列,满足条件:m*n等于N;m>=n;且m-n取所有可能值中的最小值。
#include<iostream>
#include<vector>
#include<algorithm>
#include <math.h>
using namespace std;
int main() {
int N;
cin >> N;
vector<int> A(N);
for (int i = 0;i<N;i++)
cin >> A[i];
//当只输入一个数时直接输出
if (N == 1)
{
cout << A[0] << endl;
return 0;
}
sort(A.begin(), A.end());
int a=sqrt(N);
while (N % a != 0) --a;
int c= N / a;
int m = c, n = a;
vector< vector<int> > B(m, vector<int>(n, 0));
int direct[] = { 0,1,2,3 }, d = 0, posD = 0; //控制方向:向右,向下,向左,向上。
int x = 0, y = 0, posA = N-1;
while (posA>=0)
{
if ((x == m || x<0) || (y == n || y<0)|| B[x][y] != 0)//方向调转,碰到边界或者下一个数已经
{
++posD;
switch (d) //之前已经超过边界一格了,所以要回退一步。
{
case 0: y--;x++;break;
case 1:x--;y--;break;
case 2:y++;x--;break;
case 3: x++;y++;break;
}
d = direct[posD % 4];
}
B[x][y] = A[posA];--posA; //往二维数组填充数据。
switch (d) //一直往上面设定的方向行走和填充。
{
case 0: y++;break;
case 1:x++;break;
case 2:y--;break;
case 3: x--;break;
}
}
for (int h = 0;h<m;h++) //打印结果
{
for (int l = 0;l<n;l++)
{
cout << B[h][l];
if (l != n - 1)
{
cout << " ";
}
}
cout << endl;
}
return 0;
}
- 开根号定义在math.h
- 当N=11*21时,开根号后得到的数一定位于m和n之间。通过递减直到余数为0
- 通过vector构造二维数组。
- 在判断是否需要调整方向时,是3个或。注意只要前面有条件为真,就不再进行后面的判断。(参考的做法使用的是内置数组,可以向前(下标为-1)越界访问,但是vector不行。所以改进将判断内容是否为0放在最后)
- 判断内容是否为0用于数组内层的迭代;判断x和y是否越界用于外层循环
- 通过dircted数组决定方向。大大减少了编程的复杂程度。