本题要求将给定的 N 个正整数按非递增的顺序,填入“螺旋矩阵”。所谓“螺旋矩阵”,是指从左上角第 1 个格子开始,按顺时针螺旋方向填充。要求矩阵的规模为 m 行 n 列,满足条件:m×n 等于 N;m≥n;且 m−n 取所有可能值中的最小值。
输入格式:
输入在第 1 行中给出一个正整数 N,第 2 行给出 N 个待填充的正整数。所有数字不超过 104,相邻数字以空格分隔。
输出格式:
输出螺旋矩阵。每行 n 个数字,共 m 行。相邻数字以 1 个空格分隔,行末不得有多余空格。
输入样例:
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
思路:
一共有N个数,每次按从左至右、从上至下、从右至左、从下至上的顺序为数组a[m][n]赋值。
代码:
#include<stdio.h>
#include<math.h>
int main(){
int N;
scanf("%d",&N);
int m=sqrt((double)N),n=sqrt((double)N);
while(m*n!=N){
if(m*n<N) ++m;
else if(m*n>N) --n;
}
int a[N],b[m][n];
for(int i=0;i<N;++i){
scanf("%d",&a[i]);
}
for(int i=0;i<N-1;++i){
int max=i;
for(int j=i+1;j<N;++j){
if(a[j]>a[max]){
max=j;
}
}
int temp=a[i];
a[i]=a[max];
a[max]=temp;
}//降序排序
int cnt=0,cnt_N=0;
int up=0,down=m-1,left=0,right=n-1;
while(cnt<N){
for(int i=left;i<=right;++i){
b[up][i]=a[cnt_N++];
++cnt;
}//从左至右赋值
++up;
for(int i=up;i<=down;++i){
b[i][right]=a[cnt_N++];
++cnt;
}//从上至下赋值
--right;
for(int i=right;i>=left;--i){
b[down][i]=a[cnt_N++];
++cnt;
}//从右至左赋值
--down;
for(int i=down;i>=up;--i){
b[i][left]=a[cnt_N++];
++cnt;
}//从下至上赋值
++left;
}
for(int i=0;i<m;++i){
for(int j=0;j<n;++j){
printf("%d",b[i][j]);
if(j!=n-1){
printf(" ");
}
}
if(i!=m-1){
printf("\n");
}
}//输出螺旋矩阵
return 0;
}
出现的问题:
测试点1、3答案错误,测试点7段错误。
第一次修改:
经测试,当N为素数(即只有一列)时,以上方法会出现越界,因此针对对这一情况进行了特别处理。
#include<stdio.h>
#include<math.h>
int main(){
int N;
scanf("%d",&N);
int m=sqrt((double)N),n=sqrt((double)N);
while(m*n!=N){
if(m*n<N) ++m;
else if(m*n>N) --n;
}
int a[N],b[m][n];
for(int i=0;i<N;++i){
scanf("%d",&a[i]);
}
for(int i=0;i<N-1;++i){
int max=i;
for(int j=i+1;j<N;++j){
if(a[j]>a[max]){
max=j;
}
}
int temp=a[i];
a[i]=a[max];
a[max]=temp;
}
if(n==1){
for(int i=0;i<m;++i){
b[i][0]=a[i];
}
}//仅有一列
else{
int cnt=0,cnt_N=0;
int up=0,down=m-1,left=0,right=n-1;
while(cnt<N){
for(int i=left;i<=right;++i){
b[up][i]=a[cnt_N++];
++cnt;
}
++up;
for(int i=up;i<=down;++i){
b[i][right]=a[cnt_N++];
++cnt;
}
--right;
for(int i=right;i>=left;--i){
b[down][i]=a[cnt_N++];
++cnt;
}
--down;
for(int i=down;i>=up;--i){
b[i][left]=a[cnt_N++];
++cnt;
}
++left;
}
}//多于一列
for(int i=0;i<m;++i){
for(int j=0;j<n;++j){
printf("%d",b[i][j]);
if(j!=n-1){
printf(" ");
}
}
if(i!=m-1){
printf("\n");
}
}
return 0;
}
出现的问题:
测试点1依然错误。
第二次修改:
在以上的代码中,矩阵的填写终止条件为cnt<N,但并未考虑填写过程中cnt是否已经等于N,此次对此进行了修改。
#include<stdio.h>
#include<math.h>
int main(){
int N;
scanf("%d",&N);
int m=sqrt((double)N),n=sqrt((double)N);
while(m*n!=N){
if(m*n<N) ++m;
else if(m*n>N) --n;
}
int a[N],b[m][n];
for(int i=0;i<N;++i){
scanf("%d",&a[i]);
}
for(int i=0;i<N-1;++i){
int max=i;
for(int j=i+1;j<N;++j){
if(a[j]>a[max]){
max=j;
}
}
int temp=a[i];
a[i]=a[max];
a[max]=temp;
}
if(n==1){
for(int i=0;i<N;++i){
printf("%d\n",a[i]);
}
return 0;
}
else{
int cnt=0,cnt_N=0;
int up=0,down=m-1,left=0,right=n-1;
while(cnt<N){
for(int i=left;i<=right;++i){
b[up][i]=a[cnt_N++];
++cnt;
}
if(cnt==N) break;//终止条件
++up;
for(int i=up;i<=down;++i){
b[i][right]=a[cnt_N++];
++cnt;
}
if(cnt==N) break;
--right;
for(int i=right;i>=left;--i){
b[down][i]=a[cnt_N++];
++cnt;
}
if(cnt==N) break;
--down;
for(int i=down;i>=up;--i){
b[i][left]=a[cnt_N++];
++cnt;
}
if(cnt==N) break;
++left;
}
}
for(int i=0;i<m;++i){
for(int j=0;j<n;++j){
printf("%d",b[i][j]);
if(j!=n-1){
printf(" ");
}
}
if(i!=m-1){
printf("\n");
}
}
return 0;
}