B1050
个人思路
明显感觉复杂模拟题个人思路和代码思路还是不够好
首先拿到题目先想到要螺旋式写入矩阵然后输出
随后想到,能不能不写入矩阵,先找到每一行的输出规律,直接按行输出
想了半天决定看看答案思路再写
卡出上下左右四个边界,到达边界后更新边界,改变方向
参考过答案思路后
- 素数直接排序输出,否则找出合适的m,n
- cnt元素计数器作为while的循环条件
- dir表示当前填写方向
- 不同方向到达边界前正常处理,否则(从这一步开始,思路就不清晰了)
4.1.更新边界
4.2判断是第一次到达边界,做相应处理,否则
****4.2.1.判断是完全平方数m == n,做相应处理,否则
****4.2.2.做相应处理
4.3.换方向
个人思路代码
保证N = 39之前的输出正确,测试点有一个未通过
一开始还未注意到素数时,应该是m = N,n = 1
#include <bits/stdc++.h>
using namespace std;
int N;
int m, n;
vector<int> num;
int matrix[10010][10010];
int U, D, L, R;//上下左右四个边界
void init()
{
int sqr = (int)sqrt(1.0 * N);
for(int i = sqr; i >= 1; --i)
{
if(N % i == 0)
{
m = i;
break;
}
}
n = N / m;
if(n > m)
{
int temp = m;
m = n;
n = temp;
}
//行列均从下标为1开始
U = 2;
D = m - 1;
L = 2;
R = n - 1;
}
bool isPrime(int x)
{
if(x == 0 || x == 1)
return false;
int sqr = (int)sqrt(1.0 * x);
for(int i = 2; i <= sqr; ++i)
{
if(x % i == 0)
{
return false;
}
}
return true;
}
bool cmp(int a, int b)
{
return a > b;
}
int main(int argc, char *argv[]) {
scanf("%d", &N);
for(int i = 0; i < N; ++i)
{
int a;
scanf("%d", &a);
num.push_back(a);
}
sort(num.begin(), num.end(), cmp);
if(isPrime(N))//是素数
{
for(int i = 0; i < num.size(); ++i)
{
printf("%d\n", num[i]);
}
}
else//不是素数
{
init();
int cnt = 0, i = 1, j = 1;
int dir = 3;//0:上,1:下,2:左,3:右
bool isfirR = true, isfirD = true, isfirL = true;
while(cnt < N)
{
matrix[i][j] = num[cnt++];
if(dir == 3)//先向右填
{
if(j < R)
{
j++;
}
else//到达右边界 此时 j == R
{
R--;
if(isfirR)
{
j++;
isfirR = false;
}
else
{
if(m == n)
j++;
else
i++;
}
dir = 1;
}
}
else if(dir == 1)//再向下填
{
if(i < D)
{
i++;
}
else//到达下边界 此时 j == D
{
D--;
if(isfirD)
{
i++;
isfirD = false;
}
else
{
if(m == n)
i++;
else
j--;
}
dir = 2;
}
}
else if(dir == 2)//再向左填
{
if(j > L)
{
j--;
}
else//到达左边界 此时 j == L
{
L++;
if(isfirL)
{
j--;
isfirL = false;
}
else
{
if(m == n)
j--;
else
i--;
}
dir = 0;
}
}
else if(dir == 0)//再向上填
{
if(i > U)
{
i--;
}
else//到达上边界 此时 i == U
{
U++;
dir = 3;
j++;
}
}
}
for(int x = 1; x <= m; ++x)
{
for(int y = 1; y <= n; ++y)
{
printf("%d", matrix[x][y]);
if(y < n)
printf(" ");
else
printf("\n");
}
}
}
return 0;
}
本题思路
有几个值得借鉴的地方
- 特判N==1
- 在代码过程中可以提前return 0
- 循环体中 i++,j++返回内层左上角位置。这一步有点神
AC代码
#include <bits/stdc++.h>
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 argc, char *argv[]) {
int N;
scanf("%d", &N);
for(int i = 0; i < N; ++i)
{
scanf("%d", &A[i]);
}
if(N == 1)
{
printf("%d\n", A[0]);
return 0;
}
sort(A, A + N, cmp);
//计算m,n
int m = (int)ceil(sqrt(1.0 * N));
while(N % m != 0)
{
m++;
}
int n = N / m;
int i = 1, j = 1, pos = 0;
int U = 1, D = m, L = 1, R = n;
while(pos < N)
{
while(pos < N && j < R)//向右填
{
matrix[i][j] = A[pos++];
j++;
}
while(pos < N && i < D)
{
matrix[i][j] = A[pos++];
i++;
}
while(pos < N && j > L)
{
matrix[i][j] = A[pos++];
j--;
}
while(pos < N && i > U)
{
matrix[i][j] = A[pos++];
i--;
}
U++, D--, L++, R--;//更新边界
i++, j++;//位置移至内层左上角
if(pos == N - 1)
{
matrix[i][j] = A[pos++];
}
}
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;
}