模拟 poj 3106 Flip and Turn

来源:互联网 发布:工商银行数据中心待遇 编辑:程序博客网 时间:2024/05/17 02:11

题目链接:

http://poj.org/problem?id=3106

题目大意:

有一个m*n的矩阵,有10种操作,给一个操作串,求最后的矩阵。

操作'1'  :沿主对角线翻转 行列交换

操作‘2’:沿副对角线翻转  行列交换

操作‘H':沿水平方向翻转 

操作’V‘:沿竖直方向翻转

操作’A‘:顺时针旋转90度,’B':顺时针旋转180度,‘C'顺时针旋转270度。除180度行列不交换外,其他两种行列交换

操作’X‘:逆时针旋转90度,’Y‘:逆时针旋转180度,’Z‘逆时针旋转270度。除180度行列不交换外,其他两种行列交换

操作字符串最多有100000个,如果每一个操作都对矩阵的每个元素进行,肯定会超时。所以就会想到,如果把所有的操作都统一处理成简单的几种操作,最后等价处理后,再对矩阵进行一次操作,就会很简单,也不会超时。

关键是找等价关系,并且能够用数学语言等价描述。我的想法是,将十种操作都对应成H,V,和A三种操作,对每一个操作都转化成HVA的方式。

很显然有如下关系:H和V最多出现一个,因为H+V(先水平翻转再竖直翻转)=V+H(先竖直翻转再水平翻转)=A*2(顺时针旋转90度两次)。H+H=0(先水平翻转再水平翻转等于本身)同理:V+V=0 所以最后的结果集只可能是00a,01a,10a(a表示顺时针旋转90度的次数)

对于操作’1‘:等价于先逆时针旋转90度再H一次<=>先H再顺时针旋转90度一次。 XH=HA

对于操作’2‘:等价于先顺时针旋转90度再H一次<=>先H再逆时针旋转90度一次。AH=HX

对于操作’H‘:直接和前面的等价关系**a中的a(顺时针旋转90度的次数)组合成AH=HX,一直递推到V,a次顺时针全部转化为a次顺时针。

对于操作’V‘:XV=VA=AH=HX

对于’A‘,’B‘,’C‘直接加到顺时针次数上。

对于’X‘,’Y‘,’Z‘直接减到顺时针次数上。

所以用三个变量hh,vv,shun表示水平翻转次数,竖直翻转次数,顺时针旋转次数,注意是有顺序的。

XV=AH=HX AV=XH=HA

扫描每个操作,等价处理,不满足该顺序的借助等价关系改变顺序,保持该顺序不变。

详细解释代码:

#include<iostream>#include<cmath>#include<cstdio>#include<sstream>#include<cstdlib>#include<string>#include<string.h>#include<cstring>#include<algorithm>#include<vector>#include<map>#include<set>#include<stack>#include<list>#include<queue>#include<ctime>#include<bitset>#define eps 1e-6#define INF 0x3f3f3f3f#define PI acos(-1.0)#define ll __int64#define LL long long#define lson l,m,(rt<<1)#define rson m+1,r,(rt<<1)|1#define M 1000000007#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;#define Maxn 330#define M 110000char a[Maxn][Maxn],b[Maxn][Maxn];char ord[M];int m,n;void funh() //执行水平操作{    for(int i=1;i<=m;i++)        for(int j=1;j<=n;j++)            b[m-i+1][j]=a[i][j];    memcpy(a,b,sizeof(b));}void funv() //执行竖直操作{    for(int i=1;i<=m;i++)        for(int j=1;j<=n;j++)            b[i][n-j+1]=a[i][j];    memcpy(a,b,sizeof(b));}void funa() //执行顺时针旋转90度操作{    for(int i=1;i<=m;i++)        for(int j=1;j<=n;j++)            b[j][m-i+1]=a[i][j];    swap(n,m);    memcpy(a,b,sizeof(b));}int main(){   //freopen("in.txt","r",stdin);   //freopen("out.txt","w",stdout);   while(~scanf("%d%d",&m,&n))   {       for(int i=1;i<=m;i++)            scanf("%s",a[i]+1);       scanf("%s",ord);       int hh=0,ss=0;  //hh表示水平翻转次数,ss表示竖直翻转次数       int shu=0,len=strlen(ord); //shu表示顺时针旋转次数       int flag=0;       for(int i=0;i<len;i++)       {           switch(ord[i])           {               case '1':               {                   flag^=1; //行列交换                   //由 XH=HA 和 AH=HX                   if(shu)  //如果之前有顺时针旋转                       shu=(-shu+4)%4; //顺时针全部转化为逆时针                   shu=(shu+1)%4; //最后还有个A                   if(hh) //H+H=0                     hh=0;                   else if(ss) //V+H=AA                   {                       hh=0;                       ss=0;                       shu=(shu+2)%4;                   }                   else  //H=0 V=0时H=1                      hh++;               }               break;               case '2':               {                   flag^=1; //HX                   if(shu)                       shu=(-shu+4)%4;                   shu=(shu-1+4)%4; //最后有一个X                   if(hh)                       hh=0;                   else if(ss)                   {                       hh=0;                       ss=0;                       shu=(shu+2)%4;                   }                   else                     hh++;               }               break;               case 'V':               {                   if(shu) //AV=XH=HA                   {                       shu=(-(shu-1)+4)%4;                       shu=(shu+1)%4; //最后有一个A                       if(ss)                       {                           ss=0;                           hh=0;                           shu=(shu+2)%4;                       }                       else if(hh)                          hh=0;                       else                          hh++;                      break;                   }                  if(ss)                  {                      ss=0;                      hh=0;                      //shu=(shu+2)%4;                  }                  else if(hh)                  {                      ss=0;                      hh=0;                      shu=(shu+2)%4;                  }                  else                     ss++; //如果一个H和V都没有,ss++               }               break;               case 'H':               {                   if(shu)                       shu=(4-shu)%4;                   if(ss)                   {                       ss=0;                       hh=0;                       shu=(shu+2)%4;                   }                   else if(hh)                       hh=0;                   else                      hh++;               }               break;               case 'A':                 shu=(shu+1)%4;flag^=1;break;               case 'B':                  shu=(shu+2)%4;break;               case 'C':                  flag^=1;shu=(shu+3)%4;break;               case 'X':                  flag^=1;shu=(shu-1+4)%4;break;               case 'Y':                  shu=(shu-2+4)%4;break;               case 'Z':                  flag^=1;shu=(shu-3+4)%4;break;           }       }       //printf("flag:%d hh:%d ss:%d shu:%d\n",flag,hh,ss,shu);       if(hh) //注意执行顺序 H V a           funh();       else if(ss)            funv();       if(shu) //顺时针旋转次数       {           while(shu--)               funa();       }       /*if(flag)           swap(n,m);*/       printf("%d %d\n",m,n);       for(int i=1;i<=m;i++)       {           for(int j=1;j<=n;j++)                printf("%c",a[i][j]);          putchar('\n');       }   }   return 0;}




0 0
原创粉丝点击