【菜鸟进阶之路】 P4924 [1007]魔法少女小Scarlet - 洛谷

一、题目部分

选自洛谷:

P4924 [1007]魔法少女小Scarlet

二、解题过程

思路
见“提交AC答案”部分给出的注释

提交AC答案

#include 
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)这道题的难点在于正确推导顺时针&逆时针数组间转换的规律,与下面这道方块转换的题目相似,此处附上题目链接:

P1205 [USACO1.2]方块转换 Transformations

(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代码更为精简,可读性更强,这里也附上大佬的题解博客链接供大家共同学习进步:

题解 P4924 【[1007]魔法少女小Scarlet】

你可能感兴趣的:(【算法1-1】模拟与高精度,2020暑期进阶,算法学习)