PAT乙級 1050 螺旋矩陣
阿新 • • 發佈:2018-11-28
本題要求將給定的 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;
}