1. 程式人生 > >PTA - C程式設計 NoA - 二維陣列 (10道題)

PTA - C程式設計 NoA - 二維陣列 (10道題)

應該是第10次上機題目了,本次共10道題(由於具體輸入輸出的樣例題目中都有,就不在部落格裡佔篇幅複製貼上了,只把題題目和要求賦值過來):

7-1 求矩陣的區域性極大值
7-2 矩陣運算
7-3 方陣迴圈右移
7-4 判斷上三角矩陣
7-5 找鞍點
7-6 列印楊輝三角
7-7 螺旋方陣
7-8 求矩陣各行元素之和
7-9 矩陣A乘以B
7-10 組合數的和

7-1  求矩陣區域性極大值

給定M行N列的整數矩陣A,如果A的非邊界元素A[i][j]大於相鄰的上下左右4個元素,那麼就稱元素A[i][j]是矩陣的區域性極大值。本題要求給定矩陣的全部區域性極大值及其所在的位置。

輸入格式:

在第一行中給出矩陣A的行數M和列數N(3 ≤ M, N ≤ 20);最後M行,每行給出A在該行的N個元素的值。數字間以空格分隔

輸出格式:

每行按照“元素值 行號 列號”的格式輸出一個區域性極大值,其中行、列編號從1開始。要求按照行號遞增輸出;若同行有超過1個區域性極大值,則該行按列號遞增輸出。若沒有區域性極大值,則輸出“None 總行數 總列數”。

解:

    這道題很簡單,就是對於第2行到倒數第2行,第2列到倒數第2列,找有沒有比上下左右都大的數(邊界不需要判斷),因為最小也是3列所以沒有極端情況需要判斷。注意輸出行列的時候+1就行(因為從1開始)。

#include <stdio.h>
int main()
{
    int M, N, flag = 0;
    scanf("%d%d", &M, &N);
    int a[M][N];
    for(int i = 0; i < M; i++)
        for(int j = 0; j < N; j++)
            scanf("%d", &a[i][j]);
    for(int i = 1; i < M - 1; i++)
        for(int j = 1; j< N - 1; j++)
            if(a[i][j] > a[i - 1][j] && a[i][j] > a[i + 1][j] && a[i][j] > a[i][j - 1] && a[i][j] > a[i][j + 1])
            {
                printf("%d %d %d\n", a[i][j], i + 1, j + 1);
                flag = 1;
            }
    if(flag == 0) printf("None %d %d\n", M, N);
    return 0;
}

7-1  矩陣運算

給定一個n×n的方陣,本題要求計算該矩陣除副對角線、最後一列和最後一行以外的所有元素之和。副對角線為從矩陣的右上角至左下角的連線。

輸入格式:

輸入第一行給出正整數n(1<n≤10);隨後n行,每行給出n個整數,其間以空格分隔。

輸出格式:

在一行中給出該矩陣除副對角線、最後一列和最後一行以外的所有元素之和。

解:

    只需要判斷好副對角線,最後一列,最後一行就沒有任何難度。

#include <stdio.h>
int main()
{
    int n, sum = 0;
    scanf("%d", &n);
    int a[n][n];
    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
            scanf("%d", &a[i][j]);
    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
            if((i + j) != n - 1 && j != n - 1 && i != n - 1)  // 不是副對角線,不是最後一列,不是最後一行
                sum += a[i][j];
    printf("%d\n", sum);
    return 0;
}

7-3 方陣迴圈右移

本題要求編寫程式,將給定n×n方陣中的每個元素迴圈向右移m個位置,即將第0、1、⋯、n−1列變換為第n−m、n−m+1、⋯、n−1、0、1、⋯、n−m−1列。

輸入格式:

輸入第一行給出兩個正整數m和n(1 ≤ n ≤ 6)。接下來一共n行,每行n個整數,表示一個n階的方陣。

輸出格式:

按照輸入格式輸出移動後的方陣:即輸出n行,每行n個整數,每個整數後輸出一個空格。

解:

    這道題需要考慮 m > n 的情況,而且比如 3x3 的方陣,右移100位,也就是右移1位,因為每移動 n 位,就相當於沒動。也就是說,相當於右移 m % n 位

    因為每一行之間沒有任何關係,所以可以讀取一行,右移一行,輸出一行,再繼續。所以只需要一個大小為n的陣列就行了。而且因為只需要輸出,所以甚至不需要交換,或者真的去移動陣列,而是按照右移後的順序輸出就行了。比如 1 2 3 4 5,右移 2 位,不需要右移,先輸出 4 5,再輸出 1 2 3 就行了分界線為 n - m

#include <stdio.h>
int main()
{
    int m, n;   // n個大小為n的陣列,都右移m個位置
    scanf("%d%d", &m, &n);
    m %= n;
    int a[n];
    for(int row = 0; row < n; row++)
    {
        for(int i = 0; i < n; i++)        scanf("%d", &a[i]);
        for(int i = n - m; i < n; i++)    printf("%d ", a[i]);
        for(int i = 0; i < n - m; i++)    printf("%d ", a[i]);
        printf("\n");
    }
    return 0;
}

7-4 判斷上三角矩陣

上三角矩陣指主對角線以下的元素都為0的矩陣;主對角線為從矩陣的左上角至右下角的連線。

本題要求編寫程式,判斷一個給定的方陣是否上三角矩陣。

輸入格式:

輸入第一行給出一個正整數T,為待測矩陣的個數。接下來給出T個矩陣的資訊:每個矩陣資訊的第一行給出一個不超過10的正整數n。隨後n行,每行給出n個整數,其間以空格分隔。

輸出格式:

每個矩陣的判斷結果佔一行。如果輸入的矩陣是上三角矩陣,輸出“YES”,否則輸出“NO”。

解:

    只需要判斷下三角有沒有不是0的就行,for(int i = 1; i < n; i++) 和 for(int j = 0; j < i; j++) 連個迴圈條件想明白就明白了。

#include <stdio.h>
int main()
{
    int repeat;
    scanf("%d", &repeat);
    while(repeat > 0)     // 重複 repeat 次
    {
        int n, flag = 0;
        scanf("%d", &n);
        int a[n][n];
        for(int i = 0; i < n; i++)
            for(int j = 0; j <n; j++)
                scanf("%d", &a[i][j]);
        for(int i = 1; i < n; i++)      // 從第二行開始
        {
            for(int j = 0; j < i; j++)  // 每行判斷前 i 個數有沒有不是0的
                if(a[i][j] != 0)
                {
                    printf("NO\n");
                    flag = 1;
                    break;
                }
            if(flag == 1) break;
        }
        if(flag == 0) printf("YES\n");
        --repeat;
    }
    return 0;
}

7-5 找鞍點

一個矩陣元素的“鞍點”是指該位置上的元素值在該行上最大、在該列上最小

本題要求編寫程式,求一個給定的n階方陣的鞍點。

輸入格式:

輸入第一行給出一個正整數n(1≤n≤6)。隨後n行,每行給出n個整數,其間以空格分隔。

輸出格式:

輸出在一行中按照“行下標 列下標”(下標從0開始)的格式輸出鞍點的位置。如果鞍點不存在,則輸出“NONE”。題目保證給出的矩陣至多存在一個鞍點。

解:

    這題需要注意的地方就是,一行中可能有多個相同大小的最大值,比如 1 5 2 3 5 5,每一個最大值都需要判斷是不是鞍點。

#include <stdio.h>
int main()
{
    int n, flag = 0;
    scanf("%d", &n);
    int a[6][6] = {0};
    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
            scanf("%d", &a[i][j]);
    for(int i = 0; i < n; i++)
    {
        int maxA = -9999999, k, t;
        for(int j = 0; j < n; j++)    // 找出第 i 行最大值是多少
            if(a[i][j] > maxA)
                maxA = a[i][j];
        for(t = 0; t < n; t++)        // 對每一個最大值位置都判斷是不是鞍點
        {
            if(a[i][t] != maxA) continue;
            for(k = 0; k < n; k++)
                if(a[k][t] < a[i][t])
                    break;
            if(k == n)
            {
                flag = 1;
                printf("%d %d\n", i, t);
                return 0;
            }
        }
    }
    if(flag == 0) printf("NONE\n");
    return 0;
}

7-6  列印楊輝三角

本題要求按照規定格式列印前N行楊輝三角。

輸入格式:

輸入在一行中給出N(1 ≤ N ≤ 10)。

輸出格式:

以正三角形的格式輸出前N行楊輝三角。每個數字佔固定4位。

輸入樣例: 6

輸出樣例:

        1
       1   1
      1   2   1
     1   3   3   1
    1   4   6   4   1
   1   5  10  10   5   1

解:

     這道題很多人卡在了“格式錯誤”上,格式錯誤是真的坑爹= =。

#include<stdio.h>
int main()
{
    int n;
    scanf("%d",&n);
    int a[n][n];
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n - i - 1; j++) printf(" "); // 第 i 行有 n - i - 1 個字首空格
        a[i][0] = 1;  // 每行第一個數是1
        a[i][i] = 1;  // 每行最後一個數是1
        for(int j = 1; j < i; j++)
            a[i][j] = a[i - 1][j - 1] + a[i - 1][j];
        for(int j = 0; j <= i; j++)
            printf("%4d", a[i][j]);
        printf("\n");
    }
    return 0;
}

7-7 螺旋方陣

所謂“螺旋方陣”,是指對任意給定的N,將1到N×N的數字從左上角第1個格子開始,按順時針螺旋方向順序填入N×N的方陣裡。本題要求構造這樣的螺旋方陣。

輸入格式:

輸入在一行中給出一個正整數N(<10)。

輸出格式:

輸出 N×N 的螺旋方陣。每行N個數字,每個數字佔3位。

輸入樣例: 5

輸出樣例:

  1  2  3  4  5
 16 17 18 19  6
 15 24 25 20  7
 14 23 22 21  8
 13 12 11 10  9

解:

    很多同學這道題沒有思路,但是其實看一下矩陣就知道思路了。就是一個大迴圈,迴圈裡先最上邊一行從左到右,再最右邊一列從上到下,再最下邊一行從右到左,再最左邊一列從下到上,一次迴圈就結束了,二維矩陣所有位置賦值之後,按照順序輸出就行了。注意每次賦值的邊界判斷:

#include <stdio.h>
int main()
{
    int n;
    scanf("%d", &n);
    int a[n][n];
    int T = 0, D = n - 1, L = 0, R = n - 1, cur = 1;  // Top, Down, Left, Right
    while (T <= D && L <= R)
    {
        for (int col = L; col <= R; col++)  // 最上邊一行從左到右
            a[T][col] = cur++;
        ++T;
        for (int row = T; row <= D; row++)  // 最右邊一列從上到下
            a[row][R] = cur++;
        --R;
        for (int col = R; col >= L; col--)  // 最下邊一行從右到左
            a[D][col] = cur++;
        --D;
        for (int row = D; row >= T; row--)  // 最左邊一列從下到上
            a[row][L] = cur++;
        ++L;
    }
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
            printf("%3d", a[i][j]);
        printf("\n");
    }
    return 0;
}

7-8 求矩陣各行元素之和

本題要求編寫程式,求一個給定的m×n矩陣各行元素之和。

輸入格式:

輸入第一行給出兩個正整數m和n(1 ≤ m, n ≤ 6)。隨後m行,每行給出n個整數,其間以空格分隔。

輸出格式:

每行輸出對應矩陣行元素之和。

解:

    沒任何難度。每讀一行,輸出一行。

#include <stdio.h>
int main()
{
    int m, n;
    scanf("%d%d", &m, &n);
    while(m > 0)  // m行
    {
        int sum = 0;
        for(int i = 0; i < n; i++)
        {
            int tmp;
            scanf("%d", &tmp);
            sum += tmp;
        }
        printf("%d\n", sum);
        --m;
    }
    return 0;
}

7-9 矩陣A乘以B

給定兩個矩陣A和B,要求你計算它們的乘積矩陣AB。需要注意的是,只有規模匹配的矩陣才可以相乘。即若A有R​a​​行、C​a​​列,B有R​b​​行、C​b​​列,則只有C​a​​與R​b​​相等時,兩個矩陣才能相乘。

輸入格式:

輸入先後給出兩個矩陣A和B。對於每個矩陣,首先在一行中給出其行數R和列數C,隨後R行,每行給出C個整數,以1個空格分隔,且行首尾沒有多餘的空格。輸入保證兩個矩陣的R和C都是正數,並且所有整數的絕對值不超過100。

輸出格式:

若輸入的兩個矩陣的規模是匹配的,則按照輸入的格式輸出乘積矩陣AB,否則輸出Error: Ca != Rb,其中Ca是A的列數,Rb是B的行數。

解:

    按照矩陣乘法公式計算即可。

#include<stdio.h>
int main()
{
    int ra, ca, rb, cb;
    scanf("%d%d", &ra, &ca);
    int a[ra][ca];
    for(int i = 0; i < ra; i++)
        for(int j = 0; j < ca; j++)
            scanf("%d", &a[i][j]);
    scanf("%d%d", &rb, &cb);
    int b[rb][cb];
    for(int i = 0; i < rb; i++)
        for(int j = 0; j < cb; j++)
            scanf("%d", &b[i][j]);
    // 如果矩陣1的列數不等於矩陣2的行數,則報錯退出
    if(ca != rb)  printf("Error: %d != %d\n", ca, rb);
    else
    {
        printf("%d %d\n", ra, cb);
        for(int i = 0; i < ra; i++)
            for(int j = 0; j < cb; j++)
            {
                int sum=0;
                for(int k = 0; k < ca; k++)
                    sum += a[i][k] * b[k][j];
                if(j < cb - 1)  printf("%d ",sum);
                else            printf("%d\n",sum);
            }
    }
    return 0;
}

7-10 組合數的和

給定 N 個非 0 的個位數字,用其中任意 2 個數字都可以組合成 1 個 2 位的數字。要求所有可能組合出來的 2 位數字的和。例如給定 2、5、8,則可以組合出:25、28、52、58、82、85,它們的和為330。

輸入格式:

輸入在第一行中給出 N(1 < N < 10),隨後一行給出 N 個不同的非 0 個位數字。數字間以空格分隔。

輸出格式:

輸出所有可能組合出來的2位數字的和。

解:

    “不同”兩個字把難度又降了不少,把所有數字讀到一個數組中,然後遍歷就好了。

#include <stdio.h>
int main()
{
    int n,sum = 0;
    scanf("%d", &n);
    int a[n];
    for(int i = 0; i < n; i++)
        scanf("%d", &a[i]);
    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
            if(i != j)
                sum += a[i] * 10 + a[j];
    printf("%d\n", sum);
    return 0;
}