PAT (Basic Level) Practice 1050 螺旋矩陣
阿新 • • 發佈:2018-12-20
乙級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個迴圈,直接迴圈四個方向,再縮排