首页 > 技术文章 > NOI 练手题 图像旋转翻转变换

CXSheng 2015-10-18 11:59 原文

题目:来源http://noi.openjudge.cn/ch0112/09/

总时间限制: 
1000ms
 
内存限制: 
65536kB
描述

给定m行n列的图像各像素点灰度值,对其依次进行一系列操作后,求最终图像。

其中,可能的操作及对应字符有如下四种:

A:顺时针旋转90度;

B:逆时针旋转90度;

C:左右翻转;

D:上下翻转。

输入
第一行包含两个正整数m和n,表示图像的行数和列数,中间用单个空格隔开。1 <= m <= 100, 1 <= n <= 100。
接下来m行,每行n个整数,表示图像中每个像素点的灰度值,相邻两个数之间用单个空格隔开。灰度值范围在0到255之间。
接下来一行,包含由A、B、C、D组成的字符串s,表示需要按顺序执行的操作序列。s的长度在1到100之间。
输出
m'行,每行包含n'个整数,为最终图像各像素点的灰度值。其中m'为最终图像的行数,n'为最终图像的列数。相邻两个整数之间用单个空格隔开。
样例输入
2 3
10 0 10
100 100 10
AC
解析:
    题目要求转换最终的结果。分析题目发现,它的变换情况只有两种:旋转、翻转(轴对称)。
    通过我们自己的想象可以知道:
    无论图形按照ABCD的命令怎么变换,最终也只会有八种形态:
      1.不翻转,顺时针旋转0°,即不变
      2.不翻转,顺时针旋转90°
      3.不翻转,顺时针旋转180°
      4.不翻转,顺时针旋转2700°
      5.按某一个方向翻转后,顺时针旋转0°
      6.按某一个方向翻转后,顺时针旋转90°
      7.按某一个方向翻转后,顺时针旋转180°
      8.按某一个方向翻转后,顺时针旋转270°
      (为了方便,我们同一将  “按某一个方向翻转”  改为  “按图形左边缘为对称轴进行轴对称”)
  
    于是我们可以画出图形经过翻转后的八种形态(对于我这个懒人,拿一张纸直接变换,是懒得用脑子想象的一种好方法)。
 
1       2       3       4    
1 2 3   7 4 1   9 8 7   3 6 9
4 5 6   8 5 2   6 5 4   2 5 8
7 8 9   9 6 3   3 2 1   1 4 7
                             
5       6       7       8    
3 2 1   9 6 3   7 8 9   1 4 7
6 5 4   8 5 2   4 5 6   2 5 8
9 8 7   7 4 1   1 2 3   3 6 9
  最朴素的算法,就是按照命令的形式,一次一次地翻转图形,但是这很耗时间,基本上就别想Accept了。
  我们在此基础上做了点改进:
    按照命令的形式,一次一次地翻转“图形的形态”
      ——什么意思?我们可以把图形每种样子做一个编码,就像警察发通缉令,有时候嫌疑人的照片一张不够:戴牛仔帽的,穿夹克的,叼雪茄的……我们也是如此(如上图所示)
  我们在一个函数中完成对命令的解析,传回图形最后的形态(给它一顿最后的晚餐~~)。
  之后也有一种优化的方法:
    原来我们想着就直接把图形真正做一个变换,但是如果图形太大,这也很耗时间;
    所以我们不妨从输出下手,改变输出的顺序,来达到变换图形的效果。
代码:(为人类造福)
  1 #include <stdio.h>
  2 #include <string.h>
  3 struct command{
  4     char str[101];
  5     int length;
  6 };
  7 int ExplainCommand(struct command s);
  8 void Print(int *pho,int way,int height,int width);
  9 int main()
 10 {
 11     int m,n,i,j;
 12     int pho[10000];
 13     struct command s;
 14     
 15     
 16     scanf("%d%d",&m,&n);
 17     for(i=0;i<m;i++)
 18     {
 19         for(j=0;j<n;j++)
 20         {
 21             scanf("%d",&pho[i*n+j]);
 22         }
 23     }
 24     getchar();
 25         gets(s.str);
 26         s.length=strlen(s.str);
 27         
 28         Print(pho,ExplainCommand(s),m,n);
 29     
 30     return 0;
 31 }
 32 int ExplainCommand(struct command s)//对命令行做解析,分析出最终的形态 
 33 {
 34     int ans=1;//假定目前最终形态为不变
 35     int i;
 36     for(i=0;i<s.length;i++)
 37     {
 38         if(s.str[i]=='A')
 39         {
 40             switch(ans)
 41             {
 42                 case 1:    ans=2    ;break;
 43                 case 2:    ans=3    ;break;
 44                 case 3:    ans=4    ;break;
 45                 case 4:    ans=1    ;break;
 46                 case 5:    ans=6    ;break;
 47                 case 6:    ans=7    ;break;
 48                 case 7:    ans=8    ;break;
 49                 case 8:    ans=5    ;break;
 50             }
 51         }
 52         
 53         else if(s.str[i]=='B')
 54         {
 55             switch(ans)
 56             {
 57                 case 1:    ans=4    ;break;
 58                 case 2:    ans=1    ;break;
 59                 case 3:    ans=2    ;break;
 60                 case 4:    ans=3    ;break;
 61                 case 5:    ans=8    ;break;
 62                 case 6:    ans=5    ;break;
 63                 case 7:    ans=6    ;break;
 64                 case 8:    ans=7    ;break;
 65             }
 66         }
 67         else if(s.str[i]=='C')
 68         {
 69             switch(ans)
 70             {
 71                 case 1:    ans=5    ;break;
 72                 case 2:    ans=8    ;break;
 73                 case 3:    ans=7    ;break;
 74                 case 4:    ans=6    ;break;
 75                 case 5:    ans=1    ;break;
 76                 case 6:    ans=4    ;break;
 77                 case 7:    ans=3    ;break;
 78                 case 8:    ans=2    ;break;
 79             }
 80         }
 81         else if(s.str[i]=='D')
 82         {
 83             switch(ans)
 84             {
 85                 case 1:    ans=7    ;break;
 86                 case 2:    ans=6    ;break;
 87                 case 3:    ans=5    ;break;
 88                 case 4:    ans=8    ;break;
 89                 case 5:    ans=3    ;break;
 90                 case 6:    ans=2    ;break;
 91                 case 7:    ans=1    ;break;
 92                 case 8:    ans=4    ;break;
 93             }
 94         }
 95     } 
 96     return ans;
 97 }
 98 void Print(int *pho,int way,int height,int width)
 99 {
100 /*图形经过各种旋转变换后,最后的形态只有8种 
101  *前四种: 
102  *1=未翻转,顺时针旋转 0
103  *2=未翻转,顺时针旋转 90
104  *3=未翻转,顺时针旋转 180
105  *4=未翻转,顺时针旋转 270
106  *后四种: 
107  *5=以图形左边为对称轴对称,顺时针旋转 0
108  *6=以图形左边为对称轴对称,顺时针旋转 90
109  *7=以图形左边为对称轴对称,顺时针旋转 180
110  *8=以图形左边为对称轴对称,顺时针旋转 270
111  */ 
112      int i,j,temp;
113      
114      
115     if(way==1)
116     {
117         for(i=0;i<height;i++)
118         {
119             for(j=0;j<width;j++)
120             {
121                 temp=*(pho+i*width+j);
122                 printf("%d ",temp);
123             }
124             printf("\n");
125         }
126     }
127     
128     
129     else if(way==2)
130     {
131         for(j=0;j<width;j++)
132         {
133             for(i=height-1;i>=0;i--)
134             {
135                 temp=*(pho+i*width+j);
136                 printf("%d ",temp);
137             }
138             printf("\n");
139         }
140     }
141     
142     
143     else if(way==3)
144     {
145         for(i=height-1;i>=0;i--)
146         {
147             for(j=width-1;j>=0;j--)
148             {
149                 temp=*(pho+i*width+j);
150                 printf("%d ",temp);
151             }
152             printf("\n");
153         }
154     }
155     
156     
157     else if(way==4)
158     {
159         for(j=width-1;j>=0;j--)
160         {
161             for(i=0;i<height;i++)
162             {
163                 temp=*(pho+i*width+j);
164                 printf("%d ",temp);
165             }
166             printf("\n");
167         }
168         
169     }
170     
171     
172     else if(way==5)
173     {
174         for(i=0;i<height;i++)
175         {
176             for(j=width-1;j>=0;j--)
177             {
178                 temp=*(pho+i*width+j);
179                 printf("%d ",temp);
180             }
181             printf("\n");
182         }
183     }
184     
185     
186     else if(way==6)
187     {
188         for(j=width-1;j>=0;j--)
189         {
190             for(i=height-1;i>=0;i--)
191             {
192                 temp=*(pho+i*width+j);
193                 printf("%d ",temp);
194             }
195             printf("\n");
196         }
197     }
198     
199     
200     else if(way==7)
201     {
202         for(i=height-1;i>=0;i--)
203         {
204             for(j=0;j<width;j++)
205             {
206                 temp=*(pho+i*width+j);
207                 printf("%d ",temp);
208             }
209             printf("\n");
210         }
211     }
212     
213     
214     else if(way==8)
215     {
216         for(j=0;j<width;j++)
217         {
218             for(i=0;i<height;i++)
219             {
220                 temp=*(pho+i*width+j);
221                 printf("%d ",temp);
222             }
223             printf("\n");
224         }
225     }
226     
227     return ;
228 }
不点开就不用花钱

 请不要问我为什么不用二维数组——因为在传参数的时候真心不好用……

 即使是用指针也如此(因为我不会呀~~)

 

推荐阅读