一、题目部分
选自洛谷:
二、解题过程
思路
见“提交AC答案”部分给出的注释
提交AC答案
#include<bits/stdc++.h>
using namespace std;
int n,m;//n和m分别表示方阵大小和魔法施放次数
int x[501],y[501],r[501],z[501];
//把以第x行第y列为中心的2r+1阶矩阵按照某种时针方向旋转
//z=0表示顺时针,z=1表示逆时针
int a[501][501],change[501][501];//初始矩阵及临时存储矩阵
int west,east,up,down;//矩阵旋转边界
int main()
{
scanf("%d %d",&n,&m);
for(int i=0;i<m;i++)
scanf("%d %d %d %d",&x[i],&y[i],&r[i],&z[i]);
//初始化矩阵
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
a[i][j]=n*(i-1)+j;
// for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=n;j++)
// printf("%d ",a[i][j]);
// printf("\n");
// }
for(int k=0;k<m;k++)
{
west=x[k]-r[k];
east=x[k]+r[k];
up=y[k]-r[k];
down=y[k]+r[k];
//顺时针90°
if(z[k]==0)
{
for(int i=west;i<=east;i++)
for(int j=up;j<=down;j++)
change[x[k]-y[k]+j][x[k]+y[k]-i]=a[i][j];
for(int i=west;i<=east;i++)
for(int j=up;j<=down;j++)
a[i][j]=change[i][j];
}
//逆时针90°
else if(z[k]==1)
{
for(int i=west;i<=east;i++)
for(int j=up;j<=down;j++)
change[x[k]+y[k]-j][y[k]-x[k]+i]=a[i][j];
for(int i=west;i<=east;i++)
for(int j=up;j<=down;j++)
a[i][j]=change[i][j];
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
printf("%d ",a[i][j]);
printf("\n");
}
return 0;
}
三、小结
(1)这道题的难点在于正确推导顺时针&逆时针数组间转换的规律,与下面这道方块转换的题目相似,此处附上题目链接:
(2)方块转换题其实我在5月已经试水AC过了,那道题相比这道题推导规律的难度较低,因为是对整个矩阵进行相应的转换操作,只要细心一点理清思路就能做了,晚点我会把我做过的那道题的AC代码也一并记录下来。而今天这道题相当于方块转换题的进阶版,它是在一个整体的矩阵里取一部分矩阵并对该部分进行旋转操作,规律我大概推导了一个早上还是没有想出来,所以
//顺时针
change[x[k]-y[k]+j][x[k]+y[k]-i]=a[i][j];
//逆时针
change[x[k]+y[k]-j][y[k]-x[k]+i]=a[i][j];
这两个转换的规律和代码我是有参考 @黎曦の夜 大佬的做法的,且大佬的题解比我上面的AC代码更为精简,可读性更强,这里也附上大佬的题解博客链接供大家共同学习进步: