【头歌】算法与竞赛(第14章) - 矩阵基本运算

第1关:运用矩阵求解A+rX=B


任务描述

本关任务:给定两个相同大小的矩阵A和矩阵B,以及一个系数r,运用矩阵的基本运算法则编写一个程序计算A+rX=B的解:矩阵X

例如等式:

可以求得矩阵X为:

相关知识

为了完成本关任务,你需要掌握:1.矩阵的加法与减法,2.矩阵与数的乘法。

矩阵的加法与减法

矩阵定义:由m×n个数按照mn列的形式而排成的数表称之为mn列的矩阵,简称m×n矩阵。用符号记作为A=(aij),其中i=1,2..mj=1,2..n

m×n个数称为矩阵A的元素,简称为元。矩阵A的第i行第j列元素用aij表示,称为矩阵A(i,j)元。

矩阵的加法和减法运算定义为逐个元素进行加法或减法,因此两个矩阵的行数、列数分别相等。给定矩阵A和矩阵B,如下:

它们的加减法运算为A±B

简而言之,两个矩阵的加减就是它们相同位置的元素的加减。特别的,矩阵加法运算满足以下运算性质:

  • 交换律:A+B=B+A

  • 结合律:(A+B)+C=A+(B+C)

矩阵与数的乘法

设矩阵A是一个m×n的矩阵,r是一个实数,则数r与矩阵A相乘的结果为一个相同大小的矩阵,记为rA

简单来说,数r乘矩阵A,就是将数r乘矩阵A中的每一个元素。特别的,数乘也满足一些运算性质:

  • 结合律:(r1×r2)×A=r1×(r2×A)

  • 分配律:r×(A+B)=r×A+r×B

编程要求

本关的编程任务是补全右侧代码片段operator +operator -BeginEnd中间的代码,具体要求如下:

  • operator +中,运用矩阵的基本加法运算法则,计算两个矩阵(结构体内部矩阵指针this和参数矩阵B)的加法,并返回加法运算后的结果矩阵。

  • operator -中,运用矩阵的基本减法运算法则,计算两个矩阵的减法,并返回减法运算后的结果矩阵。

  • operator *中,运用矩阵的基本数乘运算法则,计算矩阵与数的乘法,并返回数乘运算后的结果矩阵。

测试说明

平台将自动编译补全后的代码,并生成若干组测试数据,接着根据程序的输出判断程序是否正确。

以下是平台的测试样例:

测试输入: 3 3 2 3 -1 2 1 5 7 2 4 5 7 5 -2 5 1 9 4 2 1 预期输出: 2.00 3.00 -2.00 2.00 -2.00 1.00 1.00 -1.00 -2.00

输入格式: 第1行:矩阵A和矩阵B的大小(m,n) 第2行:系数r 接下来m行(每行n个数):矩阵A 接下来m行(每行n个数):矩阵B 输出格式: mn列的矩阵


开始你的任务吧,祝你成功!

#include <iostream>
#include <algorithm>

using namespace std;

struct Matrix {
    int m, n;
    double **val;
    Matrix() {}
    Matrix(int m_, int n_) {
        m = m_;
        n = n_;
        this->val = (double **)malloc(sizeof(double *) * m);
        for (int i = 0; i < m; i++) {
            this->val[i] = (double *)malloc(sizeof(double) * n);
        }
    }
    void in() {
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                scanf("%lf", &this->val[i][j]);
            }
        }
    }
    void out() {
        for (int i = 0; i < m; i++) {
            printf("%.2lf", this->val[i][0]);
            for (int j = 1; j < n; j++) {
                printf(" %.2lf", this->val[i][j]);
            }
            printf("\n");
        }
    }
    Matrix operator + (const Matrix B) const {
        Matrix result(m, n);  // 创建一个新矩阵来存储结果

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                result.val[i][j] = this->val[i][j] + B.val[i][j];  // 将对应位置的元素相加
            }
        }

        return result;  // 返回结果矩阵
    }
    Matrix operator - (const Matrix B) const {
        Matrix result(m, n);  // 创建一个新矩阵来存储结果

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                result.val[i][j] = this->val[i][j] - B.val[i][j];  // 将对应位置的元素相减
            }
        }

        return result;  // 返回结果矩阵
    }
    Matrix operator * (const double r) const {
        Matrix result(m, n);  // 创建一个新矩阵来存储结果

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                result.val[i][j] = this->val[i][j] * r;  // 将每个元素乘以给定的数
            }
        }

        return result;  // 返回结果矩阵
    }
};

int main(int argc, const char * argv[]) {

    int m, n;
    double r;
    scanf("%d %d", &m, &n);
    scanf("%lf", &r);

    Matrix A(m, n);
    A.in();
    Matrix B(m, n);
    B.in();

    Matrix C(m, n);
    C = (B - A) * 0.5;  // 进行矩阵减法和数乘操作
    C.out();

    return 0;
}

第2关:矩阵乘法的运用


任务描述

本关任务:学习矩阵乘法的运算法则,编程实现给定的两个矩阵AB的乘法运算。

例如矩阵AB分别为:

它们的乘法运算结果为矩阵C=A×B

相关知识

为了完成本关任务,你需要掌握:1.矩阵的乘法。

矩阵的乘法

矩阵乘法是矩阵基础运算中最为复杂的,也是最为重要的运算。两个矩阵相乘,首先需要满足的相乘的基本条件:对于矩阵A和矩阵B,只有当矩阵A的列数等于矩阵B的行数时,矩阵A才能乘以矩阵B,即A×B,否则它们不能进行乘法运算。因此,做矩阵乘法运算的两个矩阵也不能随便跟换位置。

运算定义:设矩阵Am×p阶的矩阵,矩阵Bp×n阶的矩阵:

则矩阵A和矩阵B的乘积记做ABA×B,结果为矩阵C

其中每一项cij表达式如下:

由此可以看出,矩阵A和矩阵B相乘后得到的矩阵C的行数与左矩阵A的行数相同,列数与右矩阵B的列数相同,即C=(cij)m×n。矩阵C中第i行第j列的元素由矩阵A的第i行的元素与矩阵B的第j列的元素对应相乘,然后再取乘积之和。

虽然根据矩阵乘法运算的定义可以得出矩阵乘法不满足交换律的性质,但是矩阵乘法仍然有很多实用的性质,比如:

  • 结合律:对于矩阵ABC,若A的列数等于B的行数,B的列数又等于C的行数,则有以下等式成立: (AB)C=A(BC) α(AB)=(αA)B=A(αB)

  • 分配律:(A+B)C=AC+BCC(A+B)=CA+CB

编程要求

本关的编程任务是补全右侧代码片段operator *BeginEnd中间的代码,具体要求如下:

  • operator *中,根据矩阵的乘法运算法则,在矩阵结构体中,实现矩阵乘法的重载函数:计算两个矩阵(结构体内部矩阵指针this和参数矩阵B)的乘法,并返回乘法运算后的结果矩阵。
测试说明

平台将自动编译补全后的代码,并生成若干组测试数据,接着根据程序的输出判断程序是否正确。

以下是平台的测试样例:

测试输入: 2 2 1 2 1 -1 2 3 1 2 -3 -1 1 2 预期输出: -1 4 1 2 1 -5

输入格式: 1行:矩阵Amp 接下来m行,每行p列(矩阵A 1+m行:矩阵Bpn 接下来p行,每行n列(矩阵B 输出格式: 乘法运算后的矩阵C


开始你的任务吧,祝你成功!

#include <iostream>
#include <algorithm>

using namespace std;

struct Matrix {
    int m, n;
    int **val;
    Matrix() {}
    Matrix(int m_, int n_) {
        m = m_;
        n = n_;
        this->val = (int**)malloc(sizeof(int*) * m);
        for (int i = 0; i < m; i++) {
            this->val[i] = (int*)malloc(sizeof(int) * n);
            for (int j = 0; j < n; j++) {
                this->val[i][j] = 0; // 初始化为零
            }
        }
    }
    void in() {
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                scanf("%d", &this->val[i][j]);
            }
        }
    }
    void out() {
        for (int i = 0; i < m; i++) {
            printf("%d", this->val[i][0]);
            for (int j = 1; j < n; j++) {
                printf(" %d", this->val[i][j]);
            }
            printf("\n");
        }
    }
    Matrix operator * (const Matrix B) const {
        Matrix result(m, B.n);
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < B.n; j++) {
                result.val[i][j] = 0;
                for (int k = 0; k < n; k++) {
                    result.val[i][j] += this->val[i][k] * B.val[k][j];
                }
            }
        }
        return result;
    }

};

int main(int argc, const char * argv[]) {

    int m1, n1;
    scanf("%d %d", &m1, &n1);
    Matrix A(m1, n1);
    A.in();

    int m2, n2;
    scanf("%d %d", &m2, &n2);
    Matrix B(m2, n2);
    B.in();

    Matrix C = A * B; // 使用重载的*操作符进行矩阵相乘
    C.out();

    return 0;
}

第3关:矩阵转置的运用


任务描述

本关任务:学习矩阵转置的运算法则,编程实现给定的矩阵A的转置运算。

例如给定的矩阵A为:

它的转置运算结果矩阵T为:

相关知识

为了完成本关任务,你需要掌握:1.矩阵的转置。

矩阵的转置

转置运算定义:将矩阵A的行换成同序号的列(行与列进行交换)所得到的新矩阵称为矩阵A的转置矩阵,记作AT或$$A^{`}$$。

设矩阵Am×n阶矩阵:

A的转置矩阵ATn×m阶矩阵:

同时,根据矩阵转置运算的定义我们可以得出如下性质:

  • (AT)T=A,矩阵转置的转置等于自身;

  • (A+B)T=AT+BT,两个矩阵的和的转置等于各个矩阵转置之后的和;

  • (AB)T=BTAT,两个矩阵的乘积的转置等于相反顺序的各个矩阵的转置之后的乘;

  • (αA)T=αAT,数与矩阵乘法后的转置矩阵等于数乘以转置矩阵的矩阵。

编程要求

本关的编程任务是补全右侧代码片段TransposeBeginEnd中间的代码,具体要求如下:

  • Transpose中,根据矩阵的转置运算法则,在矩阵结构体中,实现矩阵的转置,并返回转置运算后的结果矩阵。
测试说明

平台将自动编译补全后的代码,并生成若干组测试数据,接着根据程序的输出判断程序是否正确。

以下是平台的测试样例:

测试输入: 2 4 1 0 3 -1 2 1 0 2 预期输出: 1 2 0 1 3 0 -1 2

输入格式: 1行:矩阵Amn 接下来m行,每行n列(矩阵A 输出格式: 转置运算后的矩阵T


开始你的任务吧,祝你成功!

#include <iostream>
#include <algorithm>

using namespace std;

struct Matrix {
    int m, n;
    int **val;
    Matrix() {}
    Matrix(int m_, int n_) {
        m = m_;
        n = n_;
        this->val = (int **)malloc(sizeof(int *) * m);
        for (int i = 0; i < m; i++) {
            this->val[i] = (int *)malloc(sizeof(int) * n);
        }
    }
    void in() {
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                scanf("%d", &this->val[i][j]);
            }
        }
    }
    void out() {
        for (int i = 0; i < m; i++) {
            printf("%d", this->val[i][0]);
            for (int j = 1; j < n; j++) {
                printf(" %d", this->val[i][j]);
            }
            printf("\n");
        }
    }
    Matrix Transpose() const {
        Matrix result(n, m); // 创建一个新的矩阵来存储转置结果
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                result.val[j][i] = this->val[i][j]; // 将原矩阵的行变成新矩阵的列
            }
        }
        return result;
    }
};

int main(int argc, const char *argv[]) {

    int m, n;
    scanf("%d %d", &m, &n);
    Matrix A(m, n);
    A.in();

    Matrix C(n, m);
    C = A.Transpose();
    C.out();

    return 0;
}

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值