Portal: Character Wheels
Title
Give you an n*n matrix, and ensure that n is even. There are a total of n/2 layers from the outside to the inside. Now there are m operations. For each operation:
- Select one of the layers to turn left (counterclockwise) or right (clockwise) y times.
- Output the current matrix.
Ideas
Direct simulation.
- If you want to output the matrix. For each layer, maintain a linear table in the order of upper left -> upper right -> lower right -> lower left of the matrix. If you need to output a new matrix, traverse the linear table and store the answer matrix according to its corresponding position.
- If you want to select a layer, rotate it y times. Set num=y%4, if num!=0, rotate to the right num times, which is equivalent to rotate 4-num times to the left. Then update the starting position of each layer in the corresponding linear table.
AC code
#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 simplified
In fact, you don't need to put them in the linear table in order, you can directly modify the original matrix, swap 4 positions each time to adjust the order.
#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;
}