CFgym Board Queries (旋转、翻转简化)

http://codeforces.com/gym/100497

codeforces

2014-2015 CT S02E04: Codeforces Trainings Season 2 Episode 4 (US College Rockethon 2014 + COCI 2008-5 + GCJ Finals 2008 C)

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 }
View Code

 

另外输入的好莱森是垂直翻转,另一个是水平翻转……看来英文的说法和汉语不太一样?

posted @ 2014-10-04 01:34  带鱼Yuiffy  阅读(300)  评论(0编辑  收藏  举报