题目链接
题目分析
简单的模拟题目
解题思路
1、遍历1-sqrt(N)
,得到最接近的m, n(m > n)
2、顺时针旋转:
寻找规律,每次到达边界其实转向是确定的,
记录当前的运行方向,并在边界时改变走向即可
注意点
二维数组的初始化,一开始想节省点时间,写成fill(vis[0], vis[0]+(N+1)*(n+1), false)
实际并不会严格给要用到的小矩阵赋值,会一行一行往下走,所以出错;
AC程序(C++)
/**********************************
*@ID: 3stone
*@ACM: PAT.A1105 Spiral Matrix
*@Time: 18/9/20
*@IDE: VScode 2018 + clang++
***********************************/
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 1010;
int N;
int matrix[maxn][maxn];
bool vis[maxn][maxn]; //标记是否填入了数字
priority_queue<int> Q; //存储数据,便于堆排序
void find_matrix(int& n, int& m) {
int sqt = (int)sqrt((1.0) * N);
for(int i = sqt; i>= 1; i--) {
if(N % i == 0) {
n = i;
break;
}
}
m = N / n;
}
//判断是否需要更改方向
void judgeDirection(int& i, int& j, int& direction, int n, int m) {
switch(direction) {
case 1:
j--;//go left
if(j < 0 || vis[i][j] == true) { //frontier or used
j++; //recover
i--; direction = 3; //true on
}
break;
case 2:
j++;//go right
if(j >= n || vis[i][j] == true) {
j--;
i++; direction = 4; //turn down
}
break;
case 3:
i--; //go up
if (i < 0 || vis[i][j] == true) {
i++;
j++; direction = 2; //turn right
}
break;
case 4:
i++; // go down
if(i >= m || vis[i][j] == true) {
i--;
j--; direction = 1; //true on
}
break;
//default:
}//switch
}
int main() {
int n, m, temp;
while(scanf("%d", &N) != EOF) {
for(int i = 0; i < N; i++) {
scanf("%d", &temp);
Q.push(temp);
}
//fill(vis[0], vis[0] + maxn * maxn, false); //也可以,数组并不大
for(int i = 0; i < m; i++)
fill(vis[i], vis[i] + n, false);
//find m and n
find_matrix(n, m);
//how to intial the matrix clockwisely
int direction = 2; //go right at first
int i = 0, j = 0;
while(!Q.empty()) {
matrix[i][j] = Q.top();
Q.pop();
vis[i][j] = true;
//方向1,2,3,4 分别表示左右上下
judgeDirection(i, j, direction, n, m);
}//while
//output the matrix
for(int i = 0; i < m; i++) {
for(int j = 0; j < n - 1; j++) {
printf("%d ", matrix[i][j]);
}
printf("%d\n", matrix[i][n - 1]);
}
}//while-scanf
return 0;
}