经典矩阵入门题

题目:点的变换

资料:http://www.matrix67.com/blog/archives/276/

主要思路:

                      

                              (附图来自Matrix67大神)


注意点:对于各种操作,转化成矩阵之后,开始我随便写的Wa了一次,后来才发现我忘了矩阵乘法的不可交换性,所以对于一次给定的操作O1,O2,...On,初始矩阵B,我们运算的顺序应该是ANS=On * ..(. *(O2 * (O1 * B))) 然后根据结合律,所有的操作合并得到O=(On*....O2*O1),所以对于一次输入的操作,记住一定是左乘,右乘你就跪了。


#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define PI acos(-1.0)
struct Matrix
{
    double m[4][4];
}E,matrix[10010];
void init()
{
    for(int i=1;i<=3;i++)
        for(int j=1;j<=3;j++)
        {
            if(i==j)
                E.m[i][j]=1.0;
            else
                E.m[i][j]=0.0;
        }
}
Matrix init_translation(double _x,double _y)
{
    Matrix ans=E;
    ans.m[1][3]=_x;
    ans.m[2][3]=_y;
    return ans;
}
Matrix init_zoom(double l)
{
    Matrix ans=E;
    ans.m[1][1]=l;
    ans.m[2][2]=l;
    return ans;
}
Matrix init_up_down()
{
    Matrix ans=E;
    ans.m[2][2]=-1;
    return ans;
}
Matrix init_left_right()
{
    Matrix ans=E;
    ans.m[1][1]=-1;
    return ans;
}
Matrix Multi(Matrix A,Matrix B)
{
    Matrix ans;
    for(int i=1;i<=3;i++)
        for(int j=1;j<=3;j++)
        {
            ans.m[i][j]=0;
            for(int k=1;k<=3;k++)
                ans.m[i][j]+=A.m[i][k]*B.m[k][j];
        }
    return ans;
}
Matrix init_rotate(double r)
{
    Matrix ans=E;
    ans.m[1][1]=cos(r);
    ans.m[1][2]=-sin(r);
    ans.m[2][1]=sin(r);
    ans.m[2][2]=cos(r);
    return ans;
}
Matrix last(Matrix A,Matrix B)
{
    Matrix ans;
    for(int i=1;i<=3;i++)
        for(int j=1;j<=1;j++)
        {
            ans.m[i][j]=0;
            for(int k=1;k<=3;k++)
                ans.m[i][j]+=A.m[i][k]*B.m[k][j];
        }
    return ans;
}
int main()
{
    init();
    int N,M;
    scanf("%d%d",&N,&M);
    for(int i=1;i<=N;i++)
    {
        scanf("%lf%lf",&matrix[i].m[1][1],&matrix[i].m[2][1]);
        matrix[i].m[3][1]=1;
    }
    Matrix ans=E;
    char str[5];
    double x,y;
    for(int i=1;i<=M;i++)
    {
        scanf("%s",&str);
        if(str[0]=='X')
            ans=Multi(init_up_down(),ans);
        else if(str[0]=='Y')
            ans=Multi(init_left_right(),ans);
        else if(str[0]=='M')
        {
            scanf("%lf%lf",&x,&y);
            Matrix tmp=init_translation(x,y);
            ans=Multi(init_translation(x,y),ans);
        }
        else if(str[0]=='R')
        {
            scanf("%lf",&x);
            x/=180;
            x*=PI;
            ans=Multi(init_rotate(x),ans);
        }
        else if(str[0]=='S')
        {
            scanf("%lf",&x);
            ans=Multi(init_zoom(x),ans);
        }
    }
    for(int i=1;i<=N;i++)
    {
        matrix[i]=last(ans,matrix[i]);
        printf("%.1lf %.1lf\n",matrix[i].m[1][1],matrix[i].m[2][1]);
    }
    return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值