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;
}

猜你喜欢

转载自blog.csdn.net/Bob__yuan/article/details/84704049