【题解】LuoGu2129:L国的战斗续之多路出击

版权声明:Fashion Education https://blog.csdn.net/ModestCoder_/article/details/82084195

原题传送门
题目描述

这一次,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支军队移动后的位置。
输入样例
3 3
0 0
4 -3
6 7
x
m -1 2
y

输出样例
1 2
-3 5
-5 -5

【题解】
这是一道矩阵乘法练手题
由于我对矩阵乘法的理解不深刻,在这题上花了近1个小时。。
我一开始纠缠于一个并不是问题的问题,即我认为某个地方有问题但其实并没有问题。。。

暴力不多说,时间复杂度O(nm),显然不行
想到矩阵乘法,因为矩阵乘法最重要的性质:满足乘法结合律,是这道题有地方入手了
构造三个矩阵,下面是我的构造过程:

先发现有三种操作,而且x和y的操作比较简单,于是我首先构造除了x和y两个操作的矩阵
-1 0
0 1 <—–x的矩阵

1 0
0 -1 <—–y的矩阵

接下来构造m操作的矩阵,发现常数项p,q无法与2*2的矩阵一起运算,想到了把2*2矩阵扩充成3*3矩阵,加一个常数项系数1
下面是我构造好的3个矩阵

-1 0 0
0 1 0 <—x的矩阵
0 0 1

1 0 0
0 -1 0 <—y的矩阵
0 0 1

1 0 p
0 1 q <—m的jz
0 0 1

这样就构造好了。

矩阵乘法的方法,时间复杂度O(m+n)常数忽略了

其实本题还有一种O(m+n)的方法,且不用矩阵,也没有常数
就是定义两个量:deltax,deltay,分别表示x、y坐标增加多少,然后每次对这两个量进行操作,最后与初始坐标操作。
因为我用这题练手了矩阵乘法,这种方法我并没有编,很好理解的,不多说了。

Code:

uses math;
type
    ar = array[0..10,0..10] of int64;
var
    b,c,d,e,f:ar;
    a:array[0..1000000,1..3] of longint;
    print:array[0..10] of int64;
    n,m,p,q:int64;
    i,j,k:longint;
    ch,kongge:char;

procedure mul(var a:ar;b:ar);
var
    i,j,k:longint;

begin
    fillchar(c,sizeof(c),0);
    for i := 1 to 3 do
        for j := 1 to 3 do
            for k := 1 to 3 do
                inc(c[i][j],a[i][k] * b[k][j]);
    for i := 1 to 3 do
        for j := 1 to 3 do
            a[i][j] := c[i][j];
end;

begin
    readln(n,m);
    for i := 1 to n do
    begin
        readln(a[i][1],a[i][2]);
        a[i][3] := 1;
    end;
    for i := 1 to 3 do
        b[i][i] := 1;
    d[1][1] := -1; d[2][2] := 1; d[3][3] := 1;
    e[1][1] := 1; e[2][2] := -1; e[3][3] := 1;
    f[1][1] := 1; f[2][2] := 1; f[3][3] := 1;
    for i := 1 to m do
    begin
        read(ch);
        if ch = 'x' then mul(b,d) else
        if ch = 'y' then mul(b,e) else
        begin
            read(kongge,p,q);
            f[1][3] := p; f[2][3] := q;
            mul(b,f);
        end;
        readln;
    end;
    for i := 1 to n do
    begin
        fillchar(print,sizeof(print),0);
        for j := 1 to 2 do
            for k := 1 to 3 do
                inc(print[j],b[j][k] * a[i][k]);
        writeln(print[1],' ',print[2]);
    end;
end.

猜你喜欢

转载自blog.csdn.net/ModestCoder_/article/details/82084195