1105 Spiral Matrix (25 分)
题意
给出一组N个数,把这N个数填入一个m*n的螺旋矩阵里。该螺旋矩阵是从外一圈一圈向最中心的数单调不增。第一个数在最外圈左上角。而 m * n = N,m>=n且m与n应该是所有符合要求中相差最小的一组m,n。
input
12
37 76 20 98 76 42 53 95 60 81 58 93
output
98 95 93
42 37 81
53 20 76
58 60 76
思路
一道稍微麻烦的模拟题。思路很容易想到,先找到符合要求的m,n,并对这组数从大到小排序,再模拟螺旋矩阵依次把数填进去。
找m,n。很容易知道,n必定小于等于N开方。从N的开方往下找,第一个能整除N的数即为n,m等于N/n。
调用sort对数列排序
螺旋矩阵从第一个开始往右,然后再往下,然后再往左,然后往上,往右…
很容易发现规律:
方向上:右到下 下到左 左到上 上到右
当碰到阻碍时会换方向(超出矩阵范围,碰到已经填充数的位置)
问题
模拟题一般想思路很简单,但细节很多。可能就一个条件错了最后的结果差了十万八千里。注意各种边界和坐标。
代码
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
using namespace std;
int N, list[10007];
bool cmp(int a, int b){
return a>b;
}
int factor(int N){ //返回n
int n;
n=sqrt(N);
for(int i=n; i>=1; i--){
if(N%i == 0){
return i;
}
}
}
void matr(){
int mat[107][107], vis[107][107], x=0, y=0, m, n;
int direc[2]={0,1};
memset(vis,0,sizeof(vis));
n=factor(N);
m=N/n;
mat[0][0]=list[0];
vis[0][0]=1;
for(int i=1; i<N; i++){
if(x+direc[1]<n&&x+direc[1]>=0&&y+direc[0]<m&&y+direc[0]>=0&&vis[y+direc[0]][x+direc[1]]==0){
y+=direc[0];
x+=direc[1];
mat[y][x]=list[i];
vis[y][x]=1;
// printf("mat[%d][%d] = %d\n",y,x,mat[y][x]);
}else{
if(direc[0]==0){
if(direc[1]==1){
direc[0]=-1;
direc[1]=0;
// printf("right to down\n");
}else{
direc[0]=1;
direc[1]=0;
// printf("left to up\n");
}
}else if(direc[0]==-1){
direc[0]=0;
direc[1]=-1;
// printf("down to left\n");
}else if(direc[0]==1){
direc[0]=0;
direc[1]=1;
// printf("up to right\n");
}
i-=1;
// printf("i= %d\n",i);
}
}
for(int i=0; i<m; i++){
if(i!=0){
printf("\n");
}
for(int j=0; j<n; j++){
if(j!=0){
printf(" ");
}
printf("%d",mat[i][j]);
}
}
}
int main()
{
// int list[10007];
scanf("%d",&N);
for(int i=0; i<N; i++){
scanf("%d",&list[i]);
}
sort(list, list+N,cmp);
// for(int i=0;i<N;i++){
// printf("%d ",list[i]);
// }
// printf("\n");
matr();
return 0;
}