例28 直線蛇形陣
問題描述
撰寫程式,將自然數1、2、…、N2按蛇形方式逐個順序存入N階方陣,例如,當N=3和N=4時的直線蛇形陣如下圖1所示,

圖1 直線蛇形陣
輸入格式
一個正整數n(1≤n≤20),
輸出格式
N階滿足要求的直線蛇形方陣,輸出時共n行,每行n個數,每個數占4列,
輸入樣例
4
輸出樣例
13 14 15 16
12 11 10 9
5 6 7 8
4 3 2 1
(1)編程思路,
從圖1可以看出,直線蛇形陣的構造是從最底行(row=N-1)向最頂行(row=0)進行的,每行的填寫在兩種方式間切換,一種方式是從右到左順序(即for(j=n-1;j>=0;j--) )依次遞增1填寫,稱為方式1;另一種方式是從左到右順序(即for(j=0;j<=n-1;j++) )依次遞增1填寫,稱為方式2,
程式中定義一個變數k來標志這兩種方式,k初始值為0,表示采用方式1,當前行按方式1填寫完后,改變k的值,使其等于1,表示采用方式2,當前行按方式2填寫完后,再改變k的值,使其等于0,
(2)源程式,
#include<stdio.h>
int main()
{
int a[20][20]={0},n;
scanf("%d",&n);
int i,j,k=0,t=1;
for(i=n-1;i>=0;i--) // 遍歷行
{
if(k==0) // 從右到左順序依次遞增1存陣列元素
{
for(j=n-1;j>=0;j--)
a[i][j]=t++;
k=1;
}
else // 從左到右順序依次遞增1存陣列元素
{
for(j=0;j<=n-1;j++)
a[i][j]=t++;
k=0;
}
}
for (i=0;i<n;i++)
{
for (j=0;j<n;j++)
printf("%4d",a[i][j]);
printf("\n");
}
return 0;
}
習題28
28-1 斜線蛇形陣
問題描述
撰寫程式,將自然數1、2、…、N2按蛇形方式逐個順序存入N階方陣,例如,當N=3和N=4時的方陣如下圖2所示,
圖2 斜線蛇形陣
輸入格式
一個正整數n(1≤n≤20),
輸出格式
N階滿足要求的斜線蛇形方陣,輸出時共n行,每行n個數,每個數占4列,
輸入樣例
5
輸出樣例
15 16 22 23 25
7 14 17 21 24
6 8 13 18 20
2 5 9 12 19
1 3 4 10 11
(1)編程思路,
觀察圖2所示的斜線蛇形陣可知,方陣在逐個填數構造的程序中,是沿兩種斜線進行的,一種是斜向下,一種是斜向上,如圖3(a)所示,
設當前已填入數字的位置的行號為row(row在0~n-1之間),列號為col(col也在0~n-1之間),若按斜向下填寫,則下一位置為row++、col++ ;若按斜向上填寫,則下一位置為row--、col--,由于下一位置可能超出方陣的邊界,因此有時需要調整,調整有4種情況,下面分別進行說明,

圖3 斜線蛇形陣的構造示意圖
斜向下填寫時,會出現兩種情況:
1)超過了底行的位置(即row==n),如圖3(b)所示,3填寫好后,下一個數4的計算位置越界了,此時進行調整,方法為列col不變,row減1(即 row--),
2)超過最右列的位置(即col==n),如圖3(c)所示,15填寫好后,下一個數16的計算位置越界了,此時進行調整,方法為col--、row=row-2,
一種特例,10填寫好后,下一個數11的計算位置,行和列都越界了,但處理方法同列越界,因此在程式中應先處理col==n的情況,再處理row==n的情況,這樣對于這種特例,由于處理了col==n后,row減了2,不會越界,因此不會再處理row==n的情況,
斜向上填寫時,也會出現兩種情況:
1)超過了首行的位置(即row==-1),如圖3(d)所示,13填寫好后,下一個數14的計算位置越界了,此時進行調整,方法為row++、col=col-2,
2)超過最左列的位置(即col==-1),如圖3(e)所示,6填寫好后,下一個數7的計算位置越界了,此時進行調整,方法為row不變、列號加1(即col++),
一種特例,在如圖3(f)所示的3階方陣中,6填寫好后,下一個數7的計算位置,行和列都越界了,其處理方法同行越界,因此在程式中應先處理row==-1的情況,再處理col==-1的情況,這樣對于這種特例,由于處理了row==-1后,col加了2,不會越界,因此不會再處理col==-1的情況,
每次進行越界調整填數后,填數的方向也會發生變化,因此,可設定一個變數up,當up=1時,表示斜向上填數;up=0時,表示斜向下填數,
初始化時,令up=1、row=n-1、col=0、 num=1;在當前位置填上1(即a[row][col]=1),之后進行回圈,直到n*n個數填寫完畢,回圈中,總是先按up的方向,確定下一個位置,然后填上相應的數,例如,1向上到2,越界,調整即可,如圖3(e)所示,
(2)源程式,
#include<stdio.h>
int main()
{
int a[20][20]={0},n;
scanf("%d",&n);
int up=1;
int row=n-1;
int col=0;
int num=1;
a[row][col]=num++;
while (num<=n*n)
{
if (up) { row--; col--;}
else { row++; col++;}
if (row==-1) // 超過首行的位置
{ row++; col=col+2; up=1-up; }
if (col==n) // 超過最右列的位置
{ row=row-2; col--; up=1-up; }
if (row==n) // 超過底行的位置
{ row--; up=1-up; }
if (col==-1) // 超過最左列的位置
{ col++; up=1-up; }
a[row][col]=num++;
}
for (int i=0;i<n;i++)
{
for (int j=0;j<n;j++)
printf("%4d",a[i][j]);
printf("\n");
}
return 0;
}
若將程式中的up的初始值設定為0,即開始斜向下填寫,重新編譯并執行以上程式,則得到如下所示的結果,
5
11 19 20 24 25
10 12 18 21 23
4 9 13 17 22
3 5 8 14 16
1 2 6 7 15
28-2 對稱方陣
問題描述
圖4所示為兩個7階對稱方陣,形象起見,可將(a)方陣稱為環形對稱方陣,(b)方陣稱為三角形對稱方陣,
圖4 對稱方陣
輸入格式
兩個正整數n(1≤n≤20)和k(k為1或2),
輸出格式
N階滿足要求的對稱方陣,若k=1,輸出環形對稱方陣,k=2,輸出三角形對稱方陣,輸出時共n行,每行n個數,每個數占3列,
輸入樣例1
5 1
輸出樣例1
0 1 1 1 0
1 0 2 0 1
1 2 0 2 1
1 0 2 0 1
0 1 1 1 0
輸入樣例2
7 2
輸出樣例2
0 1 2 3 2 1 0
1 0 1 2 1 0 1
2 1 0 1 0 1 2
3 2 1 0 1 2 3
2 1 0 1 0 1 2
1 0 1 2 1 0 1
0 1 2 3 2 1 0
(1)編程思路,
1)生成如圖4(a)所示的環形對稱方陣的方法,
設方陣中元素的行號為row,列號為col,為方便見,row和col均從1開始計,
方陣的主對角線(即row==col)和次對角線(即row+col==n+1)的各元素均賦值“0”,
按兩條對角線把方陣可分成上部、左部、右部與下部4個區,如圖5所示,
圖5 環形對稱方陣的四個磁區
四個磁區的賦值方式為:
上部按行號row賦值,即if (row+col<n+1 && row<col) a[row][col]=row,
下部按運算式n+1-row賦值,即if (row+col>n+1 && row>col) a[row][col]=n+1-row,
左部按列號col賦值,即if (row+col<n+1 && row>col) a[row][col]=col,
右部按運算式n+1-col賦值,即if (row+col>n+1 && row<col) a[row][col]=n+1-col,
2)生成如圖4(b)所示的三角形對稱方陣的方法,
令m=(n+1)/2,按圖6(a)所示分成4個區,

圖6 三角形對稱方陣的四個磁區
仔細分析這個四個磁區的元素值與行號、列號的關系,并參照圖6(b)所示的7階對稱方陣各元素的值,可歸納出:
左上區(row<=m && col<=m)與右下區(row>m && col>m)參照主對角線賦值:
a[row][col]=abs(row-col) ,
右上區((row<=m && col>m)與左下區(row>m && col<=m)參照次對角線賦值:
a[row][col]= abs(row+col-n-1),
(2)源程式,
#include <stdio.h>
#include <math.h>
int main()
{
int n,k,row,col,a[21][21]={0};
scanf("%d%d",&n,&k);
if (k==1)
{
for (row=1; row<=n; row++)
for (col=1; col<=n; col++)
{
if (row==col || row+col==n+1)
a[row][col]=0; // 方陣對角線元素賦值
if (row+col<n+1 && row<col)
a[row][col]=row; // 方陣上部元素賦值
if (row+col<n+1 && row>col)
a[row][col]=col; // 方陣左部元素賦值
if (row+col>n+1 && row>col)
a[row][col]=n+1-row; // 方陣下部元素賦值
if (row+col>n+1 && row<col)
a[row][col]=n+1-col; // 方陣右部元素賦值
}
}
else
{
int m=(n+1)/2;
for (row=1; row<=n; row++)
for (col=1; col<=n; col++)
{
if ((row<=m && col<=m) || (row>m && col>m))
a[row][col]=abs(row-col); // 方陣左上部與右下部元素賦值
if ((row<=m && col>m) || (row>m && col<=m))
a[row][col]=abs(row+col-n-1); // 方陣右上部與左下部元素賦值
}
}
for (int i=1;i<=n;i++)
{
for (int j=1;j<=n;j++)
printf("%3d",a[i][j]);
printf("\n");
}
return 0;
}
28-3 螺旋下三角陣
問題描述
撰寫程式,將自然數1、2、…、(1+N)*N/2按螺旋方式逐個順序存入N階下三角矩陣,例如,當N=3和N=4時的矩陣如下圖7所示,
圖7 螺旋下三角陣
輸入格式
一個正整數n(1≤n≤20),
輸出格式
N階滿足要求的螺旋下三角陣,輸出時每個數占4列,
輸入樣例
5
輸出樣例
1 2 3 4 5
12 13 14 6
11 15 7
10 8
9
(1)編程思路
螺旋下三角陣的構造可以看成由向右填充(行號不變、列號加1,即col++)、斜向下填充(row++、col--)和向上填充(行號減1、列號不變,即row--)三個子程序不斷交替完成的,
例如,圖8所示的3階螺旋下三角陣可以看成由向右填充(1、2、3),斜向下填充(4、5)和向上填充(6)這3個子程序完成的,4階螺旋下三角陣可以看成由向右填充(1、2、3、4),斜向下填充(5、6、7)、向上填充(8、9)和向右填充(10)這4個子程序完成的,
n階螺旋下三角陣可以看成由n個子程序完成,每個子程序為向右填充、斜向下填充和向上填充這三種中的一種,用變數direction來表示,其取值為0、1或2,0表示向右填充,1表示斜向下填充,2表示向上填充,每個子程序結束后,切換填充方向,方式為:
direction=(direction+1)%3;
n個子程序中,第1個子程序填寫n個數,第2個子程序填寫n-1個數,…,最后一個子程序填寫1個數,因此,程式總體寫成一個二重回圈,描述為:
for (i=n;i>=1;i--)
{
for (j=1;j<=i;j++)
{
按填充方向,填充相應資料
}
direction=(direction+1)%3; // 切換填充方向
}
初始時,注意row=0,col=-1,這樣向右col++后,col為0,正好填在第1個位置,
(2)源程式,
#include <stdio.h>
int main()
{
int a[20][20]={0},row,col,i,j,n,num;
int direction=0;
scanf("%d",&n);
row=0; col=-1; num=1;
for (i=n;i>=1;i--)
{
for (j=1;j<=i;j++)
{
switch(direction)
{
case 0:col++;break; // 向右填充
case 1:row++;col--;break; // 斜向下填充
case 2:row--;break; // 向上填充
}
a[row][col]=num++;
}
direction=(direction+1)%3; // 切換填充方向
}
for(row=0;row<n;row++)
{
for(col=0;col<n-row;col++)
printf("%4d",a[row][col]);
printf("\n");
}
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/51137.html
標籤:C
下一篇:eclipse 添加主題
