zoukankan      html  css  js  c++  java
  • L国的战斗续之多路出击(洛谷P2129)——基础的矩阵乘法

    题目背景

    广而告之:背景见其他L国的战斗!!大家一起刷

    题目描述

    这一次,L国决定军队分成n组,分布在各地,若以L国为原点,可以看作在一个直角坐标系内。但是他们都受统一的指挥,指令部共发出m个命令。命令有移动、上下转移和左右转移(瞬移??),但是由于某些奇奇怪怪的原因,军队收到命令总是有延迟,为了方便,军方已经写好一个栈(那还要我干嘛,自己都写好不就行了?),所以你要处理的顺序,应该是从后往前。

    输入输出格式

    输入格式:

    输入文件army.in包括n+m+1行

    第一行两个整数n、m

    接下来n行

    第i行有两个整数xi yi表示第i支军队的位置。

    又是m行

    每行首先是一个字符 C

    若C为m 则紧跟两个整数 p q 表示把每支军队的位置从(xi,yi)移到(xi+p.yi+q)

    若C为x 则表示把每支军队的位置从(xi,yi)移到(-xi,yi)

    若C为y 则表示把每支军队的位置从(xi,yi)移到(xi,-yi)

    输出格式:

    输出文件army.out包含n行

    第i行有两个整数xi、yi,表示第i支军队移动后的位置。

    输入输出样例

    输入样例#1:
    3 3
    0 0
    4 -3
    6 7
    x
    m -1 2
    y
    
    输出样例#1:
    1 2
    -3 5
    -5 -5
    

    说明

    对于30%的数据 1≤n≤1000 1≤m≤1000

    对于100%的数据 1≤n≤500000 1≤m≤500000 Ai在longint范围内

    ———————————分割线———————————

    终于……我还是写了一道矩阵的例题。废话不多说先来讲题吧。

    首先我们可以将每一个点变成一个矩阵。

    然后,这样子就是m的操作。

    这样子就是x的操作。

    同理这样就是y的操作。

    所以!我们可以先将所有的操作先乘起来,最后得到一个矩阵和每一个点乘就可以了!

    这样的话(这个话字我不知道打了几遍……每次都是跳出来haunted……)复杂度就能大大减少!

    最后题目中倒序给出操作是为了方便我们计算!不用反过来的!设点的矩阵是A,操作(正序)分别有B,C,D。则乘的顺序一定是D*(C*(B*A))。所以结合律一用就是(D*C*B)*A。所以就不用反过来了!(之前被这个坑了很久……真的是智商捉急)。

    #include<bits/stdc++.h>
    using namespace std;
    struct nob{
    	long long mat[4][4];
    	friend nob operator * (const nob &a,const nob &b){
    		nob rem;
    		for (int i=1; i<=3; i++){
    			for (int l=1; l<=3; l++){
    				long long sum=0;
    				for (int k=1; k<=3; k++){
    					sum+=a.mat[i][k]*b.mat[k][l];
    				}
    				rem.mat[i][l]=sum;
    			}
    		}
    		return rem;
    	}
    }move[500005],ans;
    struct point{
    	long long mat[4][2];
    	friend point operator * (const point &a,const nob b){
    		point rem;
    		for (int i=1; i<=3; i++){
    			long long sum=0;
    			for (int k=1; k<=3; k++){
    				sum+=a.mat[k][1]*b.mat[i][k];
    			}
    			rem.mat[i][1]=sum;
    		}
    		return rem;
    	}
    }a[500005];
    struct oper{
    	char ch;
    	long long x,y;
    }b[500005];
    int n,m;
    nob add(long long aa,long long bb){
    	nob x;
    	x.mat[1][1]=1;x.mat[1][2]=0;x.mat[1][3]=aa;
    	x.mat[2][1]=0;x.mat[2][2]=1;x.mat[2][3]=bb;
    	x.mat[3][1]=0;x.mat[3][2]=0;x.mat[3][3]=1;
    	return x;
    }
    nob turn_x(){
    	nob x;
    	x.mat[1][1]=-1;x.mat[1][2]=0;x.mat[1][3]=0;
    	x.mat[2][1]=0;x.mat[2][2]=1;x.mat[2][3]=0;
    	x.mat[3][1]=0;x.mat[3][2]=0;x.mat[3][3]=1;
    	return x;
    }
    nob turn_y(){
    	nob x;
    	x.mat[1][1]=1;x.mat[1][2]=0;x.mat[1][3]=0;
    	x.mat[2][1]=0;x.mat[2][2]=-1;x.mat[2][3]=0;
    	x.mat[3][1]=0;x.mat[3][2]=0;x.mat[3][3]=1;
    	return x;
    }
    int main(){
    	for (int i=1; i<=3; i++){
    		for (int l=1; l<=3; l++){
    			if (i!=l) ans.mat[i][l]=0;
    			else ans.mat[i][l]=1;
    		}
    	}
    	cin>>n>>m;
    	for (int i=1; i<=n; i++){
    		cin>>a[i].mat[1][1]>>a[i].mat[2][1];
    		a[i].mat[3][1]=1;
    	}
    	for (int i=1; i<=m; i++){
    		cin>>b[i].ch;
    		if (b[i].ch=='m')
    		cin>>b[i].x>>b[i].y;
    	}
    	for (int i=1; i<=m; i++){
    		nob op;
    		if (b[i].ch=='x')
    			op=turn_x();
    		else if (b[i].ch=='y')
    			op=turn_y();
    		else op=add(b[i].x,b[i].y);
    		ans=ans*op;
    	}
    	for (int i=1; i<=n; i++){
    		a[i]=a[i]*ans;
    		cout<<a[i].mat[1][1]<<" "<<a[i].mat[2][1]<<endl;
    	}
    	return 0;
    }
    

    极其丑陋的代码

  • 相关阅读:
    cocos2d tiledmap
    cocos2d 例子编辑器
    cocos2d 粒子系统
    【leetcode】矩阵中的幸运数
    【leetcode】魔术索引
    【leetcode】多数元素
    【leetcode】整理字符串
    【leetcode】通过翻转子数组使两个数组相等
    【leetcode】珠玑妙算
    【leetcode】距离顺序排列矩阵单元格
  • 原文地址:https://www.cnblogs.com/cain-/p/7561956.html
Copyright © 2011-2022 走看看