• NYOJ 298


    利用矩阵来做变换,参考Max大神的思想的,虽然不是同一道题。

    -----------

    给定n个点,m个操作,构造O(m+n)的算法输出m个操作后各点的位置。操作有平移、缩放、翻转和旋转
        这里的操作是对所有点同时进行的。其中翻转是以坐标轴为对称轴进行翻转(两种情况),旋转则以原点为中心。如果对每个点分别进行模拟,那么m个操作总共耗时O(mn)。利用矩阵乘法可以在O(m)的时间里把所有操作合并为一个矩阵,然后每个点与该矩阵相乘即可直接得出最终该点的位置,总共耗时O(m+n)。假设初始时某个点的坐标为x和y,下面5个矩阵可以分别对其进行平移、旋转、翻转和旋转操作。预先把所有m个操作所对应的矩阵全部乘起来,再乘以(x,y,1),即可一步得出最终点的位置。

    转自M67大神

    ------

    以下是NYOJ的练习题

    感觉这种做法是十分巧妙的。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    struct Matrax {
    	double m[3][3];
    };
    double PI;
    struct Point {
    	double x,y;
    }p[10100];
    
    
    void init(Matrax &p){
    	for(int i=0;i<3;i++)
    	for(int j=0;j<3;j++)
    	p.m[i][j]=0;
    }
    
    Matrax enM(double L,double P){
    	Matrax c;
    	init(c);
    	c.m[0][0]=c.m[1][1]=c.m[2][2]=1;
    	c.m[0][2]=L;c.m[1][2]=P;
    	return c;
    }
    
    Matrax enX(){
    	Matrax c;
    	init(c);
    	c.m[1][1]=-1; 
    	c.m[0][0]=c.m[2][2]=1;
    	return c;
    }
    
    Matrax enY(){
    	Matrax c;
    	init(c);
    	c.m[0][0]=-1; 
    	c.m[1][1]=c.m[2][2]=1;
    	return c;
    }
    
    Matrax enS(double P){
    	Matrax c;
    	init(c);
    	c.m[1][1]=P; 
    	c.m[0][0]=P;c.m[2][2]=1;
    	return c;
    }
    
    Matrax enR(double R){
    	Matrax c;
    	init(c);
    	c.m[0][0]=cos(R);c.m[0][1]=-1*sin(R);
    	c.m[1][0]=sin(R);c.m[1][1]=cos(R);
    	c.m[2][2]=1; 
    	return c;
    }
    
    Matrax multi(Matrax a,Matrax b){
    	Matrax c;
    	for(int i=0;i<3;i++){
    		for(int j=0;j<3;j++){
    			c.m[i][j]=0;
    			for(int k=0;k<3;k++)
    			c.m[i][j]+=a.m[i][k]*b.m[k][j];
    		}
    	}
    	return c;
    }
    
    int main(){
    	PI=acos(-1.0);
    	int N,M;
    	double ts[3];
    	char t; double x,y,L,P,R;
    	while(scanf("%d %d",&N,&M)!=EOF){
    		Matrax ans;
    		init(ans);
    		ans.m[0][0]=ans.m[1][1]=ans.m[2][2]=1;
    		for(int i=0;i<N;i++)
    		scanf("%lf%lf",&p[i].x,&p[i].y);
    		for(int i=0;i<M;i++){
    			cin>>t;
    			Matrax tt;
    			if(t=='X'){
    				tt=enX();
    				ans=multi(tt,ans);
    			}
    			else if(t=='Y'){
    				tt=enY();
    				ans=multi(tt,ans);
    			}
    			else if(t=='M'){
    				scanf("%lf%lf",&L,&P);
    				tt=enM(L,P);
    				ans=multi(tt,ans);
    			}
    			else if(t=='S'){
    				scanf("%lf",&P);
    				tt=enS(P);
    				ans=multi(tt,ans);
    			}
    			else if(t=='R'){
    				scanf("%lf",&R);
    				R=PI*R/180.0;
    				tt=enR(R);
    				ans=multi(tt,ans);
    			}
    		}
    		for(int i=0;i<N;i++){
    			ts[0]=p[i].x; ts[1]=p[i].y; ts[2]=1;
    			double ansx=ts[0]*ans.m[0][0]+ts[1]*ans.m[0][1]+ts[2]*ans.m[0][2];
    			if(fabs(ansx-0)<1e-8) ansx=0;
    			double ansy=ts[0]*ans.m[1][0]+ts[1]*ans.m[1][1]+ts[2]*ans.m[1][2];
    			if(fabs(ansy-0)<1e-8) ansy=0;
    			printf("%.1lf %.1lf
    ",ansx,ansy);
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    scrapy-redis 分布式爬虫
    爬虫-框架-Scrapy
    MongoDB
    爬虫-请求库之-selenium
    通过位异或来交换a,b的值和通过中间变量交换a,b的值
    位运算
    sizeof运算符
    运算符和表达式(类型转换)
    为什么计算机存储的是二进制补码?
    各种进制的学习与转换
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/3950674.html
Copyright © 2020-2023  润新知