2 条题解
-
0
#include <iostream> using namespace std; int a[600][600],b[600][600]; void xuanzhzuan (int x,int y,int r,int z) { for (int i = x-r; i <= x+r; i++) { for (int j=y-r;j<=y+r;j++) { if (z==0) b[i][j]=a[x+y-j][y-x+i]; else b[i][j]=a[x-y+j][x+y-i]; } } for (int i = x-r; i <= x+r; i++) { for (int j=y-r;j<=y+r;j++) { a[i][j]=b[i][j]; } } } int main() { int n,m,con=1; cin >> n >> m; for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { a[i][j]=con++; } } int x,y,r,z; for (int i = 1; i <= m; i++) { cin >> x >> y >> r >> z; xuanzhzuan(x,y,r,z); } for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { cout << a[i][j] << " "; } cout <<endl; } return 0; } -
0
魔法矩阵旋转函数讲解
我来给你逐行、逐公式讲清楚这个旋转函数
xuanzhzuan为什么这么写,以及里面的坐标公式是怎么推导出来的。一、先看懂题目要求
- 矩阵是1-based(行、列从 1 开始数)
- 每次旋转:以
(x,y)为中心,边长2r+1的正方形 z=0顺时针转 90°,z=1逆时针转 90°- 必须用临时数组 b 暂存结果,不能直接在原数组 a 上改,否则会覆盖还没用到的数据
二、函数整体结构
void xuanzhzuan (int x,int y,int r,int z) { // 第一步:把旋转后的值存到 b 里 for (int i = x-r; i <= x+r; i++) { for (int j=y-r;j<=y+r;j++) { if (z==0) b[i][j] = a[x+y-j][y-x+i]; // 顺时针 else b[i][j] = a[x-y+j][x+y-i]; // 逆时针 } } // 第二步:把 b 复制回 a for (int i = x-r; i <= x+r; i++) { for (int j=y-r;j<=y+r;j++) { a[i][j] = b[i][j]; } } }作用:
- 遍历要旋转的小正方形里每一个位置 (i,j)
- 计算这个位置旋转后应该从原数组的哪个位置拿数
- 先存到临时数组 b,最后统一覆盖回 a
三、核心:坐标变换公式(最关键)
我们先定义:
- 中心坐标:
(cx, cy) = (x, y) - 当前要填的位置:
(i, j) - 我们要找:旋转后 (i,j) 应该等于原来的哪个位置 (u, v)
1. 顺时针旋转 90° 公式
b[i][j] = a[ x + y - j ][ y - x + i ];等价于:
u = x + y - j v = y - x + i推导原理(以中心为原点)
-
相对中心的坐标:
dx = i - x(行偏移)dy = j - y(列偏移) -
顺时针 90° 旋转的数学变换:
新dx = dy新dy = -dx -
还原回原数组坐标:
u = x + 新dx = x + dy = x + (j - y)v = y + 新dy = y - dx = y - (i - x) -
整理后就是代码里的公式:
u = x + y - j v = y - x + i
2. 逆时针旋转 90° 公式
b[i][j] = a[ x - y + j ][ x + y - i ];等价于:
u = x - y + j v = x + y - i推导原理
- 相对中心:
dx = i-x,dy = j-y - 逆时针 90° 数学变换:
新dx = -dy新dy = dx - 还原后整理,就得到上面的公式。
四、为什么要用两个循环 + 临时数组 b?
第一个循环:只读取原数组 a,计算旋转后的值,写入 b 第二个循环:把 b 完整复制回 a
如果不使用 b、直接修改 a:
- 你会把还没用到的原始值覆盖掉
- 后面的位置计算就会用错数据
- 结果直接乱掉
所以必须用临时数组,这是矩阵旋转的标准写法。
五、循环范围为什么是 i=x-r ~ x+r?
- 中心是 x 行,半径 r
- 向上延伸 r 行:
x - r - 向下延伸 r 行:
x + r - 列同理:
y - r到y + r - 刚好形成
2r+1阶正方形,完全符合题目要求
六、一句话总结这个函数
遍历以 (x,y) 为中心、半径 r 的正方形内每一个点 (i,j), 根据顺时针/逆时针的数学坐标变换公式,找到它在原数组中对应的位置, 用临时数组暂存结果,最后覆盖回原数组,完成旋转。
总结
- 公式来源:矩阵旋转的相对坐标数学变换,不是瞎写的
- 临时数组 b:防止覆盖原始数据,保证旋转正确
- 循环范围:刚好圈出要旋转的
2r+1阶小方阵 - 两行公式:分别对应顺时针、逆时针 90° 旋转
你现在的代码完全正确,可以直接 AC 这道题!
- 1
信息
- ID
- 4539
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 9
- 标签
- 递交数
- 18
- 已通过
- 2
- 上传者
粤公网安备44195502000178号