PAT乙级 1050. 螺旋矩阵

题目:

本题要求将给定的 N 个正整数按非递增的顺序,填入“螺旋矩阵”。所谓“螺旋矩阵”,是指从左上角第 1 个格子开始,按顺时针螺旋方向填充。要求矩阵的规模为 m 行 n 列,满足条件:m×n 等于 N;m≥n;且 m−n 取所有可能值中的最小值。

输入格式:

输入在第 1 行中给出一个正整数 N,第 2 行给出 N 个待填充的正整数。所有数字不超过 10
​4
​​ ,相邻数字以空格分隔。

输出格式:

输出螺旋矩阵。每行 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

这道题关键是找出螺旋变化的规律,然后按要求输出。
我自己的思路是首先利用sort函数将数组排好序。然后构造四个方向变化的函数,然后一个函数结束后,立即调用后一个函数。在函数中设置每一次的限制条件。
我们将顺序划分为:右,下,左,上,这是四次变化的顺序,然后里面设置四个墙壁的值,即碰壁的时候,输入停止。每一次变化后,壁的值会相应变化。比如:每一次右输出之后,上墙壁都会加一,以后的输出到该墙壁为止。最后,在每个函数的最后设置判定结束的条件,当所有的数输完之后,就不再继续变化。

一开始只能通过24分,6个测试点。
这是因为,数组会发生溢出,二维数组的第一个[]里应该申请足够大的空间,这样就不会导致段错误。
感谢大神的博客: 陌生缘林的博客
解释不太好,而且代码也比较繁琐,大家参考就好,大神可以忽略。自己还会想一想更好的算法,解决这个问题。

#include<iostream>
#include<algorithm>
#include<cmath>
#define M 10000
#define N 100
using namespace std;
int left(int shang,int xia,int zuo,int you,int count,int a[],int b[][N],int n);
int right(int shang,int xia,int zuo,int you,int count,int a[],int b[][N],int n);
int up(int shang,int xia,int zuo,int you,int count,int a[],int b[][N],int n);
int down(int shang,int xia,int zuo,int you,int count,int a[],int b[][N],int n);
bool cmp(int a,int b){
  return a>b;
}
int test(int x){
  for(int i=(int)sqrt(x);i>=1;i--){
    if(x%i==0){
      return i;
    }
  }
}
int right(int shang,int xia,int zuo,int you,int count,int a[],int b[][N],int n){
	for(int i=zuo;i<=you;i++){
		b[shang][i]=a[count];
		count++;
	}	
	shang++;
	if(count<n){
		down(shang,xia,zuo,you,count,a,b,n);
	}
	else{
		return 0;
	}
}
int down(int shang,int xia,int zuo,int you,int count,int a[],int b[][N],int n){
	for(int i=shang;i<=xia;i++){
		b[i][you]=a[count];
		count++;
	}
	you--;
	if(count<n){
		left(shang,xia,zuo,you,count,a,b,n);
	}
	else{
		return 0;
	}
}
int left(int shang,int xia,int zuo,int you,int count,int a[],int b[][N],int n){
	for(int i=you;i>=zuo;i--){
		b[xia][i]=a[count];
		count++;
	}
	xia--;
	if(count<n){
		up(shang,xia,zuo,you,count,a,b,n);
	}
	else{
		return 0;
	}
}
int up(int shang,int xia,int zuo,int you,int count,int a[],int b[][N],int n){
	for(int i=xia;i>=shang;i--){
		b[i][zuo]=a[count];
		count++;
	}
	zuo++;
	if(count<n){
		right(shang,xia,zuo,you,count,a,b,n);
	}
	else{
		return 0;
	}
}
int main(){
  int n;
  cin>>n;
  int a[M];
  int b[M][N]={0};
  if(n==0){
  	cout<<endl;
  }
  else{
  	for(int i=0;i<n;i++){
    cin>>a[i];
  }
  sort(a,a+n,cmp);
  int h=test(n);
  int l=n/h;
  if(l>h){
    int temp=l;
    l=h;
    h=temp;
  }
  int shang=0,xia=h-1,zuo=0,you=l-1;
  int count=0;
  right(shang,xia,zuo,you,count,a,b,n);	
  for(int i=0;i<h;i++){
  	cout<<b[i][0];
  	for(int j=1;j<l;j++){
  		cout<<" "<<b[i][j];
  	}
  	cout<<endl;
  }
  }
  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值