题目链接:请点击
思路:先看懂题什么意思(一看题是螺旋,还以为是画圆圈那种,结果发现这样毫无规律,仔细看是线性而非曲线)。弄清楚螺旋的画法这是其一。其二是m与n,题中给出“m×n 等于 N;m≥n;且 m−n 取所有可能值中的最小值”,就是要m与n无限接近。
那么,问题就有两个:其一,矩阵怎么螺旋存储;其二,怎么让m与n无限接近。
首先,找出矩阵螺旋存储的规律,如图。
(注1)在代码中螺旋存储第1个while循环的if判断条件是y==n-count,这里之所以不是n-count-1的原因在于在if判断前总会执行y++,这样在边界处是先进行了y++在判断,则y会比正常的边界值大1,所以是n-count并且在if中重新让y再减回来。在第2个while循环的判断条件仍是y=n-count-1。同理其他边界取值
其次,解决如何让m与n无限接近。这个相对上面容易理解。用一个for循环,初试i=1,当i*i<N时执行反之结束,每次循环i+1。在for中判断N是否可以整除i,若是则当前i为n(因为,i是从较小数1开始,则也应是m与n中较小的那一个n),则用N/n得m。
代码:
#include<iostream>
#include<algorithm>
using namespace std;
bool cmp(int a,int b){
return a>b;
}
int main(){
int N;
while(cin>>N){
int num[N];
for(int i=0;i<N;i++)
cin>>num[i];
sort(num,num+N,cmp);//非递增排序
int m,n,sub;
for(int i=1;i*i<=N;i++){
if(N%i==0){
n=i;
m=N/n;
sub=m-n;
}
if(sub<0) break;
}
int metrix[m][n];
int x=0,y=0,count=0,i=0;
while(i<N){
while(x==count&&i<N){
metrix[x][y]=num[i];
y++;
i++;
if(y==n-count){//判断条件说明见上方注1
x++;
y--;
}
}
while((y==n-count-1)&&i<N){
metrix[x][y]=num[i];
x++;
i++;
if(x==m-count){
y--;
x--;
}
}
while((x==m-count-1)&&i<N){
metrix[x][y]=num[i];
y--;
i++;
if(y==count-1){
x--;
y++;
}
}
while(y==count&&i<N){
metrix[x][y]=num[i];
x--;
i++;
if(x==count){
count++;
x++;
y++;
break;
}
}
}
for(int k=0;k<m;k++){
for(int l=0;l<n;l++){
cout<<metrix[k][l];
if(l!=n-1) cout<<" ";
}
cout<<endl;
}
}
return 0;
}