1. 程式人生 > >PAT (Basic Level) Practice 1050 螺旋矩陣

PAT (Basic Level) Practice 1050 螺旋矩陣

乙級1050
在這裡插入圖片描述
第一次看到時間限制200ms以為是找規律,找了半天沒找到,後來才覺得這應該是模擬題,模擬題意將數字“螺旋式”填充進去

1.m x n的確定
遍歷找最大公約數
如果是i~N遍歷的話 迴圈到最後出來的值必然是m,然後N/m出來的就是n,並且m必然>n,舉個栗子 就像11質數,遍歷到最後i=N,那麼這時候m=i,必然最大
還有個剪枝的好方法,這題不會在這上面刁難人的,所以怎麼做都行:
迴圈for(int i = 1; i*i<=N;i++)這裡用i*i<=N就是尋找前半邊即可,這樣剩下部分在i之後的值必然大於i,也就是先確定n,再計算出m

2.螺旋模擬
螺旋分四個方向,右、下、左、上
所以可以對四個反向直接模擬,一圈結束之後,在新的起點再來一圈,直到數字用完
每一圈要確定好方向,並且到一個位置要留意是不是到了邊界,如果到了邊界就表示要換方向了
所以將矩陣四個角的點的座標記錄下來為p1,p2,p3,p4,這四個點就是是否到邊界的標準,比如向右,就要留意x軸上的值不能超過p2的x值,如果相等,那就表示下一步就要換方向了,而且肯定是向下,以此類推。
值得注意的是,最後向上邊界並不是在p1點上,而是即將到p1點的時候就要停止換方向,設動點為p,那麼就是p.y+1 == p1.y;

此時就要開始新的一圈
對於新的一圈,之前設的端點要全往裡縮一圈,就是第二圈矩陣了
AC程式碼:

#include<bits/stdc++.h>
using namespace std;
struct coordinate{
	int x;
	int y;
};
coordinate p1,p2,p3,p4,p;
bool comp(int a,int b){
	if(a>b)	return true;
	return false;
}
int main(){
	int N;
	cin>>N;
	int *a = new int[N];
	int m,n; //行,列 
	for(int i = 1; i*i<=N;i++){
		if(N%i==0){
			n = i;
			m = N/i;
		} 
	}
	int martix[m][n];
	for(int i = 0;i<N;i++){
		scanf("%d",&a[i]);
	} 
	sort(a,a+N,comp);
	p1.x = 0,p1.y = 0;
	p2.x = n-1,p2.y = 0;
	p3.x = n-1,p3.y = m-1;
	p4.x = 0,p4.y = m-1;
	p.x = 0,p.y = 0;
	int left=1,down=0,right=0,up=0;
	for(int i = 0;i<N;i++){
		martix[p.y][p.x] = a[i];
//		printf("m[%d][%d] = %d   a[%d] = %d\n",p.y,p.x,martix[p.y][p.x],i,a[i]);
		if(left){
			if(p.x+1>p2.x){
				p.y++;
				left = 0;down = 1;
			}else{
				p.x++;
			}
		}
		else if(down){
			if(p.y+1>p3.y){
				p.x--;
				down = 0;right = 1;
			}else{
				p.y++;
			}
		}
		else if(right){
			if(p.x-1<p4.x){
				p.y--;
				right = 0;up = 1;
			}else{
				p.x--;
			}
		}
		else if(up){
			if(p.y-1==p1.y){//頂到頭的時候注意這地方程式碼有點不一樣 
				p.x++;
				up = 0;left = 1;
				p1.x++,p1.y++;
				p2.x--,p2.y++;
				p3.x--,p3.y--;
				p4.x++,p4.y--;
			}else{
				p.y--;
			}
		}
	}
	for(int i = 0;i<m;i++){
		int isfirst = 1;
		for(int j = 0;j<n;j++){
			if(isfirst){
				printf("%d",martix[i][j]);
				isfirst = 0;
			}else	printf(" %d",martix[i][j]);
		}
		printf("\n");
	}
	return 0;
}

百度了一下其它方式,基本大同小異。
因為我對演算法複雜度並不是特別熟悉,所以在模擬的地方選擇了複雜度O(n)的操作,好像好多人都是外層1個迴圈+內層4個迴圈,直接迴圈四個方向,再縮排