1. 程式人生 > >PAT乙級 1050 螺旋矩陣

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;
}

在這裡插入圖片描述