1. 程式人生 > >蛇行矩陣 蛇形填數 回形取數 蛇行系類(C語言詳解+圖解)

蛇行矩陣 蛇形填數 回形取數 蛇行系類(C語言詳解+圖解)

 

本貼 包括,蛇行矩陣  蛇形填數  回形取數  等 蛇行系類(C語言詳解)

 

                                         問題 1097: 蛇行矩陣

時間限制: 1Sec 記憶體限制: 64MB 提交: 1979 解決: 1164

題目描述

蛇形矩陣是由1開始的自然數依次排列成的一個矩陣上三角形。

輸入

本題有多組資料,每組資料由一個正整數N組成。(N不大於100)

輸出

對於每一組資料,輸出一個N行的蛇形矩陣。兩組輸出之間不要額外的空行。矩陣三角中同一行的數字用一個空格分開。行尾不要多餘的空格。

樣例輸入

5

 

樣例輸出

1 3 6 10 15
2 5 9 14
4 8 13
7 12
11

提示

來源

 

思路:觀察即可  這類題 主要是找規律 找找關聯

如圖a 觀察 可得 每一組斜線資料 從起點到終點 都是從小到大排列 因此我們只需要讓上一個終點
可以到下一個起點,就可以了,怎麼找 加上座標如圖b 再看 所有的起點和終點關於 對角線對稱所有的終點之間就差一個單位 (就是說 上一個終點(x,y) 和下一個終點(x,y++)差一個單位  y ++ 即可,而起點 和終點 關於對角線對稱  所以終點(x,y) 他對應的起點則是(y,x))。這樣 就讓上一個終點通過關係 到下一個起點了。

當然 方法很多 ,這只是個人理解。

                                圖a                                                                                         圖b

 

下面是實現程式碼:

 

#include<stdio.h>
int main()
{
    int  n;
    while(~scanf("%d", &n)){
      int a[110][110]={0};//初始化 
      int i=1,tn=n,x=0,y=0;
      // i代表 需要填的數值 tn迴圈的次數 x,y 起點座標
      while(tn--){
         while(x>=0&&y<n)a[x--][y++]=i++;
        // 邊界跳出條件  迴圈填數 x-- y++ 就代表 按左下到右上的對角線移動填數
         x++;//剛跳出邊界的x肯定變成-1了 因此要回溯下回到終點 y不用回 因為本來就要y++
         int tem=x;x=y;y=tem;// 將終點變為起點  交換座標
      }
    for(x=0;x<n;x++){//列印 上三角 圖形
       for(y=0;y<n-x;y++)  
       printf("%d ",a[x][y]); 
       printf("\n");
    }
  }
    return 0;
}

 

 

 擴充套件

 此類題 還可以擴充套件成各類蛇行方式的題 比如  S 型 ,內迴環 外迴環 等 後續再分析

 

 

擴充套件1 蛇形填數:

             

問題 1796: 蛇形填數

時間限制: 1Sec 記憶體限制: 128MB 提交: 298 解決: 68

題目描述

在 n * n 方陣裡填入 1, 2, …, n * n, 要求填成蛇形。例如 n = 4 時方陣為: 

10 11 12 1 
9 16 13 2 
8 15 14 3 
7  6  5 4

輸入

多組測試資料。
每組測試資料第一行輸入方陣的維數,即 n 的值。(n <= 100)

輸出

每組測試資料輸出結果是蛇形方陣,方陣中每行每兩個元素間空格,末尾不要有多餘空格,每個方陣後空一行。

樣例輸入

3

樣例輸出

7 8 1 
6 9 2 
5 4 3

 

思路分析:感覺有點 dfs的感覺 不裝南牆不變方向 這裡南牆指的 方陣的邊界或前進方向的格子裡面有數填進去了。

正題, 就是在執行下一步之前先預判一下當前你想到的下一個格子是否在方陣範圍內是否有數已經填進去了。 只有 在方陣內 並且 格子裡面沒有被填過 則可以移動到格子裡填數。下面是程式碼 不多 可以閱讀下 理理思路。

  AC 程式碼

#include<stdio.h>
int main()
{
    int n;
    while(~scanf("%d",&n)){
        int x=0,y=n-1,num=1;int a[100][100]={0};
        a[x][y]=num++;//初始座標
        while(n*n>=num)//結束條件
        {
            while(x+1<n&&!a[x+1][y])a[++x][y]=num++;//向下
            while(y-1>=0&&!a[x][y-1])a[x][--y]=num++;//向左
            while(x-1>=0&&!a[x-1][y])a[--x][y]=num++;//向上
            while(y+1<n&&!a[x][y+1])a[x][++y]=num++;//向右
        }
        for(x=0;x<n;x++)
        {
            for (y=0;y<n;y++)
           if(y==n-1) printf("%d",a[x][y]);//注意題目要求 末尾沒空格
           else  printf("%d ",a[x][y]);
            printf("\n");
        }
         printf("\n");//注意題目要求 每個方陣空行
    }
    return 0;
}

 

 

擴充套件 2:[藍橋杯][基礎練習VIP]回形取數

 

                                        [藍橋杯][基礎練習VIP]回形取數

時間限制: 1Sec 記憶體限制: 128MB 提交: 254 解決: 66

題目描述

回形取數就是沿矩陣的邊取數,若當前方向上無數可取或已經取過,則左轉90度。一開始位於矩陣左上角,方向向下。

輸入

輸入第一行是兩個不超過200的正整數m,  n,表示矩陣的行和列。接下來m行每行n個整數,表示這個矩陣。

輸出

輸出只有一行,共mn個數,為輸入矩陣回形取數得到的結果。數之間用一個空格分隔,行末不要有多餘的空格。

樣例輸入

3  3 

1  2  3 

4  5  6 

7  8  9 

樣例輸出

1 4 7 8 9 6 3 2 5

 

 

解題思路:

      和蛇形填數 類似 不過填變成取了, 不裝南牆不變方向 這裡南牆指的 方陣的邊界或前進方向的格子裡面有數被加上標記了。(此題標記可以不要 只需要 令取了的格子賦值為1即可,這裡是為了保險起見 題目沒有明說資料範圍,我們不能妄加判斷,萬一卡了啦 )

 

正題, 就是在執行下一步之前先預判一下當前你想到的下一個格子是否在方陣範圍內是否有被取走了裡面的數。 只有 在方陣內 並且 格子裡面沒有被取過 則可以移動到格子裡取數。下面是程式碼 不多 可以閱讀下 理理思路。

 

AC 程式碼:

#include<stdio.h>
#include<string.h>
 
int main(){
     int n,m,x,y,num;int a[210][210];int f[210][210];//f[][] 標記
     while(scanf("%d%d",&n,&m)!=EOF){
       memset(f,0,sizeof(f));
       for(x=0;x<n;x++)
       for(y=0;y<m;y++)
       scanf("%d",&a[x][y]);
       num=1;x=0;y=0;
       printf("%d",a[x][y]);f[x][y]=1;//初始首位
       while(n*m>num){
           while(x+1<n&&!f[x+1][y])printf(" %d",a[++x][y]),f[x][y]=1,num++;//向下
           while(y+1<m&&!f[x][y+1])printf(" %d",a[x][++y]),f[x][y]=1,num++;//向右
           while(x-1>=0&&!f[x-1][y])printf(" %d",a[--x][y]),f[x][y]=1,num++;//向上
           while(y-1>=0&&!f[x][y-1])printf(" %d",a[x][--y]),f[x][y]=1,num++;//向右
       }
       printf("\n");//末尾空行
     }
return 0;}