题目
本题要求将给定的 N 个正整数按非递增的顺序,填入“螺旋矩阵”。所谓“螺旋矩阵”,是指从左上角第 1 个格子开始,按顺时针螺旋方向填充。要求矩阵的规模为 m 行 n 列,满足条件:m×n 等于 N;m≥n;且 m−n 取所有可能值中的最小值。
输入样例
12
37 76 20 98 76 42 53 95 60 81 58 93
输出样例
98 95 93
42 37 81
53 20 76
58 60 76
思路
1、首先确定m和n,我的方法是:从x=sqrt(N)(向下取整)开始递减,当N%x==0时,此x即为n;
2、利用qsort将数组a从大至小排序;
3、确定螺旋数组和a数组的对应关系,创建函数findorder;
4、我的findorder原理:
(1)螺旋数组的特性是不断重复地画圈(我的代码中记为轮lun),相邻两圈正好相差8个数,最大的轮(圈)拥有2m+2n-4个数;
(2)对于螺旋数组中任意一点A(x,y),A距离边界长度的最小值即为A之前的轮(圈)数,例如范例中的4*3矩阵,第二行第一列(1开始)的元素(2,1)距离上边界1,距离下边界2,距离左边界0,距离右边界3。最小值为0,所以它之前的轮数为0;
(3)轮数确定以后,就是比较繁琐的加减法,判断A点处于它所在轮的第几个元素,记为r;
(4)r加上A之前数个轮的元素数量之和,即为A点在数组a中的序列号(记得减一);
代码
int findorder(int x,int y,int m,int n)
{
int r;
int shu1=x,shu2=m-1-x; //距离上、下边界的距离
int heng1=y,heng2=n-1-y; //距离左、右边界的距离
int shu=shu1
int heng=heng1
int lun=shu
if(shu
r=shu1
else if(heng
r=heng1
else // 此时该点在圈的四个端点上,具体哪个端点需要进一步判断
{
if(shu1==heng1&&shu1
else if(shu1==heng2&&shu1
else if(shu2==heng1&&shu2
else if(shu2==heng2&&shu2
}
int o=2*m+2*n-4,i; //最外面的圈拥有元素的数目
for(i=0;i
{
r+=o-8*i;
}
return r;
}
int comp(const void*a,const void*b){
return *(int*)b-*(int*)a;
}
int main()
{
int N,m,n;
scanf("%d",&N);
int i=sqrt(N),j;
while(i>=1)
{
if(N%i==0)
{
n=i;
m=N/i;
break;
}
else i--;
}
int a[N];
for(i=0;i
qsort(a,N,sizeof(int),comp);
for(i=0; i
{
for(j=0; j
{
printf("%d",a[findorder(i,j,m,n)-1]);
if(j!=n-1)printf(" ");
}
if(i!=m-1)printf("\n");
}
return 0;
}