PAT乙级 1050 螺旋矩阵

本题要求将给定的 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;
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_37205425/article/details/84310596