矩阵乘法的经典题目_源自Matrix67_

这篇博客探讨了矩阵乘法在解决一系列经典算法问题中的应用,包括平移、缩放、翻转和旋转的线性变换,快速计算矩阵的幂,以及用矩阵优化线性递推问题。通过实例介绍了如何利用矩阵来表示和解决这些问题,如求解斐波那契数列模p的值,有向图的路径计数等。
摘要由CSDN通过智能技术生成

嘛,都刷一遍好辣。
矩阵 Amn 就是一个m行n列的数表。
考虑矩阵的乘法:

C=AB=aikbkj

那么对于矩阵A的要求就是:A为m * n的矩阵
对于矩阵B的要求就是:B为n * p的矩阵
乘得的矩阵C的规模:m * p的矩阵
矩阵乘法是不满足交换律的。但它满足结合律和分配律。


经典题目1 给定n个点,m个操作,构造O(m+n)的算法输出m个操作后各点的位置。操作有平移、缩放、翻转和旋转
然后盗图
这里写图片描述
考虑实际上这个变换对应着一个类似于线性变换的东西,我们显然是可以用矩阵来搞的。
而对于翻转,旋转和缩放都是线性变换。
然而这里冒出一个平移。。
来想一想,发现肯定是多一维常量,这样就好了。
我们考虑一个向量 a⃗  经过矩阵的变换:

a⃗ =OPia⃗ 

考虑这个矩阵的操作次序,一定是需要 左乘
先翻转再平移和先平移再翻转肯定是不一样的。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define Rep(i,n) for(int i = 1;i <= n;i ++)
#define PI M_PI
using namespace std;
int n,m;
struct Mat{
  double a[4][4];}p[10005];
Mat operator*(Mat w,Mat ww)
{
    Mat c;
    Rep(i,3)Rep(j,3)c.a[i][j] = 0;
    Rep(i,3)Rep(k,3)Rep(j,3)c.a[i][j] += w.a[i][k] * ww.a[k][j];
    return c;
}
int main ()
{
    scanf("%d%d",&n,&m);
    Rep(i,n)
        scanf("%lf%lf",&p[i].a[1][1],&p[i].a[2][1]),p[i].a[3][1] = 1.0;
    Mat res;
    Rep(i,3)Rep(j,3)res.a[i][j] = (i == j);
    Rep(i,m)
    {
        getchar();
        char op;
        scanf("%c",&op);
        Mat ori;
        Rep(i,3)Rep(j,3)ori.a[i][j] = (i == j);
        if(op == 'M')
        {
            double x,y; 
            scanf("%lf%lf",&x,&y);
            ori.a[1][3] = x;ori.a[2][3] = y;
        }
        else if(op == 'X')ori.a[2][2] = -1;
        else if(op == 'Y')ori.a[1][1] = -1;
        else if(op == 'S'){
  double S;scanf("%lf",&S);ori.a[1][1] = ori.a[2][2] = S;}
        else 
        {
            
矩阵乘法是计算机科学中非常基础的一种算法,它在图像处理、人工智能等领域都有广泛的应用。而分治法是一种常见的算法思想,它可以将一个问题分成多个子问题,再将子问题的结果合并起来得到最终结果。本文将介绍如何使用分治法实现矩阵乘法。 首先,我们来回顾一下矩阵乘法的定义。对于矩阵A和B,它们的乘积C的第i行第j列的元素可以表示为: C[i][j] = sum(A[i][k] * B[k][j]), k = 1,2,...,n 其中n为矩阵的大小。 接下来,我们将使用分治法来实现矩阵乘法。具体思路如下: 1.将矩阵A和B分别划分成4个子矩阵,即A11、A12、A21、A22和B11、B12、B21、B22。 2.递归地计算子矩阵的乘积,得到C11、C12、C21和C22。 3.将C11、C12、C21和C22合并成一个大的矩阵C。 下面是Python代码实现: ```python def matrix_multiply(A, B): # 判断矩阵大小是否相等 assert len(A[0]) == len(B) # 矩阵大小为1x1的情况 if len(A) == 1 and len(A[0]) == 1 and len(B) == 1 and len(B[0]) == 1: return [[A[0][0] * B[0][0]]] # 将矩阵A和B分成4个子矩阵 A11, A12, A21, A22 = split_matrix(A) B11, B12, B21, B22 = split_matrix(B) # 递归地计算子矩阵的乘积 C11 = matrix_add(matrix_multiply(A11, B11), matrix_multiply(A12, B21)) C12 = matrix_add(matrix_multiply(A11, B12), matrix_multiply(A12, B22)) C21 = matrix_add(matrix_multiply(A21, B11), matrix_multiply(A22, B21)) C22 = matrix_add(matrix_multiply(A21, B12), matrix_multiply(A22, B22)) # 合并C11、C12、C21和C22成一个大的矩阵C return merge_matrix(C11, C12, C21, C22) def split_matrix(matrix): # 将矩阵按行、列均分为两个子矩阵 n = len(matrix) m = len(matrix[0]) A = [[matrix[i][j] for j in range(m // 2)] for i in range(n // 2)] B = [[matrix[i][j] for j in range(m // 2, m)] for i in range(n // 2)] C = [[matrix[i][j] for j in range(m // 2)] for i in range(n // 2, n)] D = [[matrix[i][j] for j in range(m // 2, m)] for i in range(n // 2, n)] return A, B, C, D def merge_matrix(A, B, C, D): # 将四个子矩阵合并成一个大的矩阵 n = len(A) + len(C) m = len(A[0]) + len(B[0]) matrix = [[0] * m for i in range(n)] for i in range(len(A)): for j in range(len(A[0])): matrix[i][j] = A[i][j] for i in range(len(C)): for j in range(len(C[0])): matrix[i + len(A)][j] = C[i][j] for i in range(len(B)): for j in range(len(B[0])): matrix[i][j + len(A[0])] = B[i][j] for i in range(len(D)): for j in range(len(D[0])): matrix[i + len(A)][j + len(A[0])] = D[i][j] return matrix def matrix_add(A, B): # 矩阵加法 n = len(A) m = len(A[0]) matrix = [[0] * m for i in range(n)] for i in range(n): for j in range(m): matrix[i][j] = A[i][j] + B[i][j] return matrix ``` 可以使用以下代码进行测试: ```python A = [[1, 2], [3, 4]] B = [[5, 6], [7, 8]] C = matrix_multiply(A, B) print(C) # [[19, 22], [43, 50]] ``` 上面的代码实现了分治法实现矩阵乘法的基本思路,但是它的时间复杂度依然是O(n^3),因为我们在合并子问题的结果时需要遍历整个矩阵。实际上,我们可以在递归计算子问题时将子矩阵的结果直接传递到合并函数中,这样可以避免重复计算,从而将时间复杂度优化到O(n^2.81)。感兴趣的读者可以自行了解 Strassen 算法的实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值