题目链接:B - Grid Rotations
题目解析:
本题题意较为简单,就是求经历过q次旋转后的新矩阵,但是显然,直接对每一个元素都进行旋转时间复杂度是O(HWQ),已经超过时间限制,所以我们要考虑旋转的性质,我们发现不管经历怎样的旋转,同一行的元素最终仍是同一行,同一列的元素仍是同一列,根据这个性质我们可以把这个二维的问题转化为两个一维的行列问题,我们分别求解(i,j)位置的元素经历过q次操作后的新行数new_row和新列数new_col。
我们对一个一维数组分析,对一个一维数组(A(a1,a2......an))进行前x个与后n-x个的180度旋转可以等价于两种操作:(1)先对原数组向右旋转x个元素(也即是把原数组的前x个元素依次移到右边),然后翻转整个数组;(2)先对原数组整个翻转,然后再把数组向右旋转n-x个元素;
根据这个性质我们可以进行如下操作,对于奇数次操作,我们等价于执行操作1,偶数次操作等价于执行操作2,这样的话两次连续的翻转可以直接抵消,最终再根据q的奇偶性判断最后是否要再次翻转。
参考代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int h,w,q;
int main()
{
scanf("%d %d",&h,&w);
vector<string>a(h);//原二维矩阵
for(int i=0;i<h;i++)cin>>a[i];
scanf("%d",&q);
vector<int>r(q),c(q);//q次操作
for(int i=0;i<q;i++)scanf("%d %d",&r[i],&c[i]);
int d_r=0,d_c=0;
for(int i=0;i<q;i++){
if(i%2==0){
//向右旋转x个元素
d_r=(d_r-r[i]+h)%h;
d_c=(d_c-c[i]+w)%w;
}
else{
//向右旋转n-x个元素
d_r=(d_r-(h-r[i])+h)%h;
d_c=(d_c-(w-c[i])+w)%w;
}
}
vector<vector<char>> b(h,vector<char>(w));
//新矩阵b,注意这里使用vector<char>类型直接建立一个二维数组
//而不是像a一样建立string类型,是因为直接建立string类型后直接访问容易出错。
for(int i=0;i<h;i++){
for(int j=0;j<w;j++){
//(i,j)-->(new_row,new_col)
int new_row=(i+d_r)%h;
int new_col=(j+d_c)%w;
if(q%2==0){
b[new_row][new_col]=a[i][j];
}
else{
b[h-1-new_row][w-1-new_col]=a[i][j];
}
}
}
for(int i=0;i<h;i++){
for(int j=0;j<w;j++)printf("%c",b[i][j]);
printf("\n");
}
return 0;
}