1. 程式人生 > >1050 螺旋矩陣——c實現

1050 螺旋矩陣——c實現

1050 螺旋矩陣 (25 分)

本題要求將給定的 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

思路:

這道題的難點總共有兩點,第一點是確定m*n;第二點是如何能夠列印螺旋矩陣。

第一個問題比較簡單,只需要對讓n=(int)sqrt(n),然後N%n==0,如果不滿足,則n--,就會找到合適的m,n。

第二個問題稍微麻煩一些,關鍵是要有處理類似問題的經驗,首先將封閉的一圈作為一個研究物件,而一圈又包含上下左右四個矩形邊的輸出,這裡就可以看到需要兩個for迴圈。注意每行的特點,一個圈子中的最上行,存資料時,行數不變列數增加;最右邊則是列數不變行數減小……依次就可以儲存進二維陣列。

注意點:還有需要注意的是如何確定螺旋轉多少圈的問題,畫了4*3的矩陣和4*4的矩陣來幫助分析,他們都是轉兩圈雖然第二圈值轉到中途。即其實每轉一圈需要用掉兩列,如果是偶數列即為n/2求圈數便可,但如果是奇數列n/2還會剩下一列同樣要轉圈,所以應該是n/2+n%2,這樣在偶數的時候取餘不起作用,在奇數的時候又可以多加1圈。

程式碼:

//1050 螺旋矩陣 v1
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int cmp(const void* a,const void* b){
	return *(int*)b-*(int*)a;	//b-a是降序,a-b是升序 
}

int main(){
	int N,n,m,i,j;	scanf("%d",&N);
	int a[N];
	for(n=0;n<N;n++)	scanf("%d",&a[n]);
	qsort(a,N,sizeof(int),cmp);
	n=(int)(sqrt(N));	//i是n 
	while(N%n!=0){	//不能整除 
		n--;
	}	
	m=N/n;	//j is m
//	printf("%d %d\n",m,n);
	int mat[m][n];
	int urow=0,drow=m-1,lcol=0,rcol=n-1,k;
	for(k=n/2+n%2;k>=0;k--){	//從外到裡遍歷的圈數 
		for(j=lcol;j<=rcol&&i!=N;j++,i++)	//遍歷最上行 	
			mat[urow][j]=a[i];
		urow++;	//最上行遍歷完畢 
		for(j=urow;j<=drow&&i!=N;j++,i++)	//遍歷最右列 
			mat[j][rcol]=a[i];
		rcol--;
		for(j=rcol;j>=lcol&&i!=N;j--,i++) 
			mat[drow][j]=a[i];
		drow--;
		for(j=drow;j>=urow&&i!=N;j--,i++)
			mat[j][lcol]=a[i];
		lcol++;
	}
	for(i=0;i<m;i++){
		for(j=0;j<n;j++){
			if(j==n-1)	printf("%d\n",mat[i][j]);
			else	printf("%d ",mat[i][j]);
		}
	}
	return 0;
}

參考:

PAT乙級1050. 螺旋矩陣(C語言)

(PAT乙級)1050 螺旋矩陣(C語言實現)