2402: 【普及-】【P4924】魔法少女小Scarlet

内存限制:128 MB 时间限制:1.000 S
评测方式:文本比较 命题人:
提交:3 解决:3

题目描述

Scarlet 最近学会了一个数组魔法,她会在 lns="http://www.w3.org/1998/Math/MathML">× 二维数组上将一个奇数阶方阵按照顺时针或者逆时针旋转 lns="http://www.w3.org/1998/Math/MathML">90

首先,Scarlet 会把 lns="http://www.w3.org/1998/Math/MathML">1 到 lns="http://www.w3.org/1998/Math/MathML">2 的正整数按照从左往右,从上至下的顺序填入初始的二维数组中,然后她会施放一些简易的魔法。

Scarlet 既不会什么分块特技,也不会什么 Splay 套 Splay,她现在提供给你她的魔法执行顺序,想让你来告诉她魔法按次执行完毕后的二维数组。

输入

第一行两个整数 lns="http://www.w3.org/1998/Math/MathML">,,表示方阵大小和魔法施放次数。

接下来 lns="http://www.w3.org/1998/Math/MathML"> 行,每行 lns="http://www.w3.org/1998/Math/MathML">4 个整数 lns="http://www.w3.org/1998/Math/MathML">,,,,表示在这次魔法中,Scarlet 会把以第 lns="http://www.w3.org/1998/Math/MathML"> 行第 lns="http://www.w3.org/1998/Math/MathML"> 列为中心的 lns="http://www.w3.org/1998/Math/MathML">2+1 阶矩阵按照某种时针方向旋转,其中 lns="http://www.w3.org/1998/Math/MathML">=0 表示顺时针,lns="http://www.w3.org/1998/Math/MathML">=1 表示逆时针。

输出

输出 lns="http://www.w3.org/1998/Math/MathML"> 行,每行 lns="http://www.w3.org/1998/Math/MathML"> 个用空格隔开的数,表示最终所得的矩阵

样例输入 复制

5 4
2 2 1 0
3 3 1 1
4 4 1 0
3 3 2 1

样例输出 复制

5 10 3 18 15
4 19 8 17 20
1 14 23 24 25
6 9 2 7 22
11 12 13 16 21

提示

对于50%的数据,满足 lns="http://www.w3.org/1998/Math/MathML">=1

对于100%的数据 lns="http://www.w3.org/1998/Math/MathML">1,500,满足 lns="http://www.w3.org/1998/Math/MathML">1+,1+

因为矩阵是绕着某个中心lns="http://www.w3.org/1998/Math/MathML">(,)旋转的而且保证是正方形,为了得到正确的式子、便于理解,我们不妨设lns="http://www.w3.org/1998/Math/MathML">(,)为原点lns="http://www.w3.org/1998/Math/MathML">(0,0),这样稍微模拟一下就可以得到顺时针旋转90°后正方形上一点lns="http://www.w3.org/1998/Math/MathML">(,)坐标变成lns="http://www.w3.org/1998/Math/MathML">(,),逆时针旋转90°后坐标变成lns="http://www.w3.org/1998/Math/MathML">(,),然后枚举lns="http://www.w3.org/1998/Math/MathML">,即可。



注意:
这里可能有的同学不理解,我们明明在是数组上操作,数组上操作是没有负号的,你上面怎么用直角坐标系来推导?那个负号怎么办啊?

其实,在数组中,我们并不是从lns="http://www.w3.org/1998/Math/MathML">(0,0)这个点为中心的,而是以lns="http://www.w3.org/1998/Math/MathML">(,)为中心,就是每个推导的结果在横坐标和纵坐标上要分别加上lns="http://www.w3.org/1998/Math/MathML">,就是可解决到负号的问题,这个也就是坐标平移的意思了。




#include<bits/stdc++.h>

using namespace std;
const int N = 510;
int n, m;
int x, y, r, z;
int a[N][N], b[N][N];
int cnt;
// 数组b为最后输出的结果数组,a为辅助数组;
int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            b[i][j] = a[i][j] = ++cnt;
    while (m--) {//m次指令
        cin >> x >> y >> r >> z;
        if (z == 0) { //顺时针
            for (int i = -r; i <= r; i++) //i为以(x,y)为中点的偏移量,可以用来描述横坐标
                for (int j = -r; j <= r; j++)//j为以(x,y)为中点的偏移量,可以用来描述纵坐标
                    //防止自己覆盖掉自己,在副本上操作
                    //遍历每一个范围内的坐标,根据上图,确定最终的坐标
                    b[x + j][y - i] = a[x + i][y + j];
        } else if (z == 1) {//逆时针
            for (int i = -r; i <= r; i++)
                for (int j = -r; j <= r; j++)
                    //防止自己覆盖掉自己,在副本上操作
                    //遍历每一个范围内的坐标,根据上图,确定最终的坐标
                    b[x - j][y + i] = a[x + i][y + j];
        }  
        for (int i = 1; i <= n; i++) //更新辅助数组
            for (int j = 1; j <= n; j++)
                a[i][j] = b[i][j];
    }
    //输出
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) cout << b[i][j] << ' ';
        cout << endl;
    }
    return 0;
}