传送门:Character Wheels
题意
给你一个n*n的矩阵,保证n为偶数。从外向内总共n/2层,现在有m次操作,对于每次操作:
- 选择其中一层向左(逆时针)或向右(顺时针)转动y次。
- 输出当前的矩阵。
思路
直接模拟。
- 如果要输出矩阵。对于每层,按矩阵的左上->右上->右下->左下的顺序维护一个线性表。若需输出新矩阵则遍历该线性表,按其对应位置存入答案矩阵即可。
- 如果要选择一层转动y次。设num=y%4,若num!=0,则向右转动num次,等效于向左转动4-num次。然后更新每一层在对应线性表中的开始位置。
AC代码
#include <bits/stdc++.h>
using namespace std;
const int N=52;
int n,m;
char a[N][N],ans[N][N];
int dir[4][2]={0,1,1,0,0,-1,-1,0}; // 右、下、左、上
vector<char>g[N]; // 按矩阵的左上->右上->右下->左下的顺序维护一个线性表
int pos[N]; // 记录第i层的首个字符在g[i]中的下标
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cin>>a[i][j];
int h=n/2; // h层
for(int i=1;i<=h;i++)
{
pos[i]=0;
int bx=i;
int by=i;
int k=0; // 方向
int x=bx,y=by;
while(1)
{
if(k==3&&x==bx&&y==by)break; // 向上回到起点,结束
g[i].push_back(a[x][y]);
int d=(h-i+1)*2-1;
if(k==0&&x==bx&&y==by+d) // 右上角,改变方向
k++;
else if(k==1&&x==bx+d&&y==by+d) // 右下角
k++;
else if(k==2&&x==bx+d&&y==by) // 左下角
k++;
x+=dir[k][0];
y+=dir[k][1];
}
}
cin>>m;
char opt;
while(m--)
{
cin>>opt;
int k,num;
if(opt=='P')
{
for(int i=1;i<=h;i++)
{
int bx=i,by=i;
int x=bx,y=by;
int cnt=pos[i];
int k=0; // 方向
while(1)
{
if(k==3&&x==bx&&y==by)break; // 向上回到起点,结束
ans[x][y]=g[i][cnt];
cnt=(cnt+1)%g[i].size(); // 记得取模
int d=(h-i+1)*2-1;
if(k==0&&x==bx&&y==by+d) // 右上角,改变方向
k++;
else if(k==1&&x==bx+d&&y==by+d) // 右下角
k++;
else if(k==2&&x==bx+d&&y==by) // 左下角
k++;
x+=dir[k][0];
y+=dir[k][1];
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
j==n?printf("%c\n",ans[i][j]):printf("%c",ans[i][j]);
}
else
{
cin>>k>>num;
num%=4;
if(opt=='R'&&num!=0)num=4-num; // 转换成L
int d=(h-k+1)*2-1;
pos[k]=(pos[k]+num*d)%g[k].size();
}
}
return 0;
}
UPDATE 2020.11.1 简化
其实不用按顺序放到线性表里,可直接修改原矩阵,每次交换4个位置,来调整顺序。
#include <bits/stdc++.h>
using namespace std;
const int N=52;
int n,m;
char s[N][N];
void rot(int k,int num) // 第k层左转num次
{
int h=n/2; // 共h层
int d=(h+1-k)*2; // 第k层行(列)的长度
while(num--)
{
for(int i=1;i<=d-1;i++)
{
int x1=k,y1=k+i-1; // 左上角往右第i个 (x1,y1)
int x2=k+i-1,y2=k+d-1; // 右上角往下第i个 (x2,y2)
int x3=k+d-1,y3=k+d-i; // 右下角往左第i个 (x3,y3)
int x4=k+d-i,y4=k; // 左下角往上第i个 (x4,y4)
swap(s[x1][y1],s[x2][y2]);
swap(s[x2][y2],s[x3][y3]);
swap(s[x3][y3],s[x4][y4]);
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++)
cin>>s[i]+1;
cin>>m;
while(m--)
{
char opt;
cin>>opt;
if(opt=='P')
{
for(int i=1;i<=n;i++)
printf("%s\n",s[i]+1);
}
else
{
int k,num;
cin>>k>>num;
num%=4;
if(opt=='R'&&num!=0)num=4-num; // 转换成L
rot(k,num);
}
}
return 0;
}