洛谷题单指南-模拟和高精度-P4924 [1007] 魔法少女小Scarlet

原题链接:https://www.luogu.com.cn/problem/P4924

题意解读:

根据题意,通过模拟法,枚举每一个要旋转的矩阵,执行旋转操作即可,关键点在于如何进行矩阵旋转。

设定矩阵int a[][], 临时矩阵int t[][]用于保存旋转后的矩阵,矩阵长度为len。

先考虑要旋转的区域左上角是a[0][0]的情况,区域内每个元素下标值是i,j,i∈[0, len-1],j∈[0, len-1]。

1、顺时针旋转90度:

先以行的角度看坐标如何变换:

可以看出,行号经过顺时针旋转90度后,变成了反向的列号。

再以列的角度看坐标如何变换:

可以看出,列号经过顺时针旋转90度后,变成了行号。

因此,对int a[i][j]执行顺时针旋转的操作,保存到int t[][]中,为

t[j][len - i - 1] = a[i][j]行号i变成了反向的列号len - i - 1,列号j变成了行号)

如果旋转的区域左上角不是a[0][0],而是a[x][y],变换时行+x,列+y即可,为

t[x + j][y + len - i - 1] = a[x + i][y + j]

2、逆时针旋转90度:

先以行的角度看坐标如何变换:

可以看出,行号经过顺时针旋转90度后,变成了列号。

再以列的角度看坐标如何变换:

可以看出,列号经过顺时针旋转90度后,变成了反向的行号。

因此,对int a[i][j]执行逆时针旋转的操作,保存到int t[][]中,为

t[len - j - 1][i] = a[i][j]行号i变成了列号,列号j变成了反向的行号len - j - 1)

如果旋转的区域左上角不是a[0][0],而是a[x][y],变换时行+x,列+y即可,为

t[x + len - j - 1][y + i] = a[x + i][y + j]

100分代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 505;

int a[N][N], t[N][N];
int n, m;

//将左上角是x,y,边长len的矩形旋转90度,z=0顺时针,z=1逆时针
void rotate(int x, int y, int len, int z)
{
    for(int i = 0; i < len; i++)
        for(int j = 0; j < len; j++)
            if(z == 0) t[x + j][y + len - i - 1] = a[x + i][y + j];  
            else t[x + len - j - 1][y + i] = a[x + i][y + j];
            
    for(int i = 0; i < len; i++)
        for(int j = 0; j < len; j++)    
            a[x + i][y + j] = t[x + i][y + j];
}

int main()
{
    cin >> n >> m;

    //初始化
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++) 
            a[i][j] = (i - 1) * n + j;

    int x, y, r, z;
    //执行魔法
    for(int i = 1; i <= m; i++)
    {
        cin >> x >> y >> r >> z;
        int dx = x - r; //待旋转的矩形区域左上角x坐标
        int dy = y - r; //待旋转的矩形区域左上角y坐标
        int l = 2 * r + 1; //待旋转的矩形区域边长
        rotate(dx, dy, l, z); //旋转90度
    }        
    //输出结果
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= n; j++) cout << a[i][j] << " ";
        cout << endl;
    }

    return 0;
}

 

posted @ 2024-01-18 17:01  五月江城  阅读(33)  评论(0编辑  收藏  举报