2402: 【普及-】【P4924】魔法少女小Scarlet
内存限制:128 MB
时间限制:1.000 S
评测方式:文本比较
命题人:
提交:3
解决:3
题目描述
Scarlet 最近学会了一个数组魔法,她会在 二维数组上将一个奇数阶方阵按照顺时针或者逆时针旋转 。
首先,Scarlet 会把 到 的正整数按照从左往右,从上至下的顺序填入初始的二维数组中,然后她会施放一些简易的魔法。
Scarlet 既不会什么分块特技,也不会什么 Splay 套 Splay,她现在提供给你她的魔法执行顺序,想让你来告诉她魔法按次执行完毕后的二维数组。
输入
第一行两个整数 ,表示方阵大小和魔法施放次数。
接下来 行,每行 个整数 ,表示在这次魔法中,Scarlet 会把以第 行第 列为中心的 阶矩阵按照某种时针方向旋转,其中 表示顺时针, 表示逆时针。
输出
输出 行,每行 个用空格隔开的数,表示最终所得的矩阵
样例输入 复制
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%的数据,满足
对于100%的数据 ,满足 。
因为矩阵是绕着某个中心旋转的而且保证是正方形,为了得到正确的式子、便于理解,我们不妨设为原点,这样稍微模拟一下就可以得到顺时针旋转90°后正方形上一点坐标变成,逆时针旋转90°后坐标变成,然后枚举即可。
注意:
其实,在数组中,我们并不是从这个点为中心的,而是以为中心,就是每个推导的结果在横坐标和纵坐标上要分别加上就是可解决到负号的问题,这个也就是坐标平移的意思了。
这里可能有的同学不理解,我们明明在是数组上操作,数组上操作是没有负号的,你上面怎么用直角坐标系来推导?那个负号怎么办啊?
#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; }