CFgym Board Queries (旋转、翻转简化)
http://codeforces.com/gym/100497
codeforces
D题
题意:给出一个n*n方阵,原始全为点,给出m个操作,操作有三种:
1.将x,y为左上角的3*3的格替换为给出的3*3矩阵(元素为点或者X)
2.顺时针/逆时针旋转
3.垂直/水平翻转
求最后的方阵。
题解:不用真的将方阵转来转去,只需要将当前的坐标对应到一开始的方阵的坐标,在一开始的方阵上改就行。
根据观察,转来转去翻来翻去,其实都可以由先转0~3个90度顺时针,再进行翻转而得到。
设ro为当前状态所需先转的90度的个数,mr[0]为是否垂直翻转,mr[1]为是否水平翻转。
然后,翻转操作就是改相应的mr就行。
旋转操作除了改ro,因为之前做的翻转操作不能直接当成最后做的翻转操作,mr也要进行修改。经过研究,旋转一下就swap(mr[0],mr[1])就行。
这样,我们就把无数操作得到的结果,用旋转0~3次+翻转0~2次得到。
也就是我们现在的某个坐标x y,可以换算成一开始的方阵的坐标。这个我们可以用一个函数来搞,复杂度就O(1),我都怕。
这样,m次操作,复杂度O(m)。最后输出方阵,复杂度O(n^2)。一共就O(n^2+m),哇。
具体实现看代码,特别简单,我自己都怕。虚拟训练中还怒拿了1血,我自己都怕。
代码:
1 //#pragma comment(linker, "/STACK:102400000,102400000") 2 #include<cstdio> 3 #include<cmath> 4 #include<iostream> 5 #include<cstring> 6 #include<algorithm> 7 #include<cmath> 8 #include<map> 9 #include<set> 10 #include<stack> 11 #include<queue> 12 using namespace std; 13 #define ll __int64 14 #define usint unsigned int 15 #define mz(array) memset(array, 0, sizeof(array)) 16 #define mf1(array) memset(array, -1, sizeof(array)) 17 #define minf(array) memset(array, 0x3f, sizeof(array)) 18 #define REP(i,n) for(i=0;i<(n);i++) 19 #define FOR(i,x,n) for(i=(x);i<=(n);i++) 20 #define RD(x) scanf("%d",&x) 21 #define RD2(x,y) scanf("%d%d",&x,&y) 22 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) 23 #define WN(x) printf("%d\n",x); 24 #define RE freopen("D.in","r",stdin) 25 #define WE freopen("1.out","w",stdout) 26 const int maxn=1111; 27 int n,m; 28 char a[maxn][maxn]; 29 char s[22]; 30 31 int ro,mr[2]; 32 33 inline void gank(int &x,int &y) { 34 int tx,i; 35 if(mr[0]==1){ 36 x=n-x+1; 37 } 38 if(mr[1]==1){ 39 y=n-y+1; 40 } 41 FOR(i,1,ro){ 42 tx=n-y+1; 43 y=x; 44 x=tx; 45 } 46 } 47 48 inline void mir(const int &q) { 49 mr[q]^=1; 50 } 51 52 inline void rot(const int &q) { 53 ro+=q+4; 54 ro%=4; 55 swap(mr[0],mr[1]); 56 } 57 58 inline void init() { 59 ro=0; 60 mz(mr); 61 } 62 63 int main() { 64 char c; 65 int x,y,i,j,k; 66 while(RD2(n,m)!=EOF) { 67 FOR(i,1,n) { 68 FOR(j,1,n) { 69 a[i][j]='.'; 70 } 71 } 72 init(); 73 FOR(i,1,m) { 74 scanf(" %s",s); 75 if(s[1]=='O') { ///ROTATE 76 scanf(" %s",s); 77 if(s[1]=='W') { ///CW 78 rot(1); 79 } else { ///CCW 80 rot(-1); 81 } 82 } else if(s[1]=='I') { ///MIRROR 83 scanf(" %s",s); 84 if(s[0]=='H') { ///HOR-¡ü¡ý 85 mir(0); 86 } else { ///VER|¡û¡ú 87 mir(1); 88 } 89 } else if(s[1]=='E') { ///REPLACE 90 scanf("%d%d",&x,&y); 91 FOR(k,x,x+2) 92 FOR(j,y,y+2) { 93 int tx=k; 94 int ty=j; 95 gank(tx,ty); 96 scanf(" %c",&a[tx][ty]); 97 } 98 } 99 //printf("%d,%d,%d\n",ro,mr[0],mr[1]); 100 } 101 FOR(i,1,n) { 102 FOR(j,1,n) { 103 x=i,y=j; 104 gank(x,y); 105 //printf("(%d,%d)",x,y); 106 putchar(a[x][y]); 107 } 108 puts(""); 109 } 110 } 111 }
另外输入的好莱森是垂直翻转,另一个是水平翻转……看来英文的说法和汉语不太一样?