图像编码

题目描述:

  有这样一副图,它有黑白像素,黑像素的坐标在1~10之间。有很多种方法来编码这个图。例如下面的图:

一种表示方法是只描述黑像素,并按x坐标的增序描述,如果x相同,则按y的增序描述,每个像素占一行。按这种编码方式的到的上面图像的编码为:

6
2 3
2 4
3 3
3 4
4 2
4 3

另一种表示方法是第一行包含最左边的黑像素的坐标,然后下一行是第一个黑像素的相邻黑像素,再下一行是第一个黑像素的第一个相邻黑像素的相邻黑像素(有点绕口,其实就是按bfs的方向描述),再下一行是第一个黑像素的第二个相邻黑像素的相邻黑像素,依次类推,直到描述完所有的黑像素。相邻像素的描述从右边开始,按逆时针方向,分别用R,T,L,B来表示,如果碰到某个相邻的黑像素已经被描诉了,就忽略描述该相邻黑像素。每一行都表示某个像素的相邻黑像素,并以“,”结尾。所有黑像素描述完后以“.”结尾。按这种编码方式的到的上面图像的编码为:

2 3
RT,
RT,
,
B,
,
.

  要求在给定的一种图像编码的情况下,给出另一种图像编码。

思路:

  如果是第一种转第二种,定义一个二维数组来表示这个图像,从最左边的那个点开始,使用bfs搜索四个方向的像素,根据是否有黑像素输出RTLB。

  1. void change_two(int lx, int by)
  2. {
  3. struct queue queue;
  4. struct coordinate coord, temp;
  5. int flag = ; //控制输出
  6.  
  7. coord.x = lx;
  8. coord.y = by;
  9. init_queue(&queue);
  10. push(&queue, coord);
  11. printf("%d %d\n", lx, by);
  12. map[lx][by] = ;
  13. while (!is_empty(queue))
  14. {
  15. if (!flag)
  16. flag = ;
  17. else
  18. printf(",\n");
  19. coord = pop(&queue);
  20. if (coord.x + <= && map[coord.x + ][coord.y])
  21. {
  22. //R
  23. temp.x = coord.x + ;
  24. temp.y = coord.y;
  25. push(&queue, temp);
  26. printf("R");
  27. map[temp.x][temp.y] = ;
  28. }
  29. if (coord.y + <= && map[coord.x][coord.y + ])
  30. {
  31. //T
  32. temp.x = coord.x;
  33. temp.y = coord.y + ;
  34. push(&queue, temp);
  35. printf("T");
  36. map[temp.x][temp.y] = ;
  37. }
  38. if (coord.x - >= && map[coord.x - ][coord.y])
  39. {
  40. //L
  41. temp.x = coord.x - ;
  42. temp.y = coord.y;
  43. push(&queue, temp);
  44. printf("L");
  45. map[temp.x][temp.y] = ;
  46. }
  47. if (coord.y - >= && map[coord.x][coord.y - ])
  48. {
  49. //B
  50. temp.x = coord.x;
  51. temp.y = coord.y - ;
  52. push(&queue, temp);
  53. printf("B");
  54. map[temp.x][temp.y] = ;
  55. }
  56. }
  57. printf(".");
  58. }

  代码20-50行分别以RTLB顺序搜索当前黑像素相邻的像素,如果有黑像素,就将其坐标压入队列,等待下次处理该像素的相邻像素,同时标记map,表示已经访问了该像素。

  如果是第二种转第一种,就是找到这个图像对应的二维数组。从给定的点开始,使用bfs来找到每个点相邻四周的黑像素,那后将这些黑像素标记到二维数组中。

  1. void change_one(int lx, int by)
  2. {
  3. struct queue queue;
  4. struct coordinate coord;
  5. struct coordinate temp;
  6. struct coordinate ans[];
  7. char line[];
  8. int i, j, maxx, maxy, n;
  9.  
  10. maxx = coord.x = lx;
  11. maxy = coord.y = by;
  12. init_queue(&queue);
  13. push(&queue, coord);
  14. map[coord.x][coord.y] = ;
  15. while (!is_empty(queue))
  16. {
  17. coord = pop(&queue);
  18. gets(line);
  19. i = ;
  20. while (line[i] != ',' && line[i] != '.')
  21. {
  22. if (line[i] == 'R')
  23. {
  24. temp.x = coord.x + ;
  25. if (temp.x > maxx)
  26. maxx = temp.x;
  27. temp.y = coord.y;
  28. }
  29. else if (line[i] == 'T')
  30. {
  31. temp.x = coord.x;
  32. temp.y = coord.y + ;
  33. if (temp.y > maxy)
  34. maxy = temp.y;
  35. }
  36. else if (line[i] == 'L')
  37. {
  38. temp.x = coord.x - ;
  39. temp.y = coord.y;
  40. }
  41. else
  42. {
  43. temp.x = coord.x;
  44. temp.y = coord.y - ;
  45. }
  46. map[temp.x][temp.y] = ;
  47. push(&queue, temp);
  48. i++;
  49. }
  50. }
  51. n = ;
  52. for (i = ; i <= maxx; i++)
  53. for (j = ; j <= maxy; j++)
  54. if (map[i][j])
  55. {
  56. ans[n].x = i;
  57. ans[n ++].y = j;
  58. }
  59. printf("%d\n", n);
  60. for (i = ; i < n; i++)
  61. printf("%d %d\n", ans[i].x, ans[i].y);
  62. }

  第二种转第一种其实是bfs的逆过程,代码第15-50行目的就是根据当前的黑色像素坐标以及输入数据来获得相邻黑色像素的坐标。

  本质上这个题目考察的就是bfs,不过这道题目的输入有点麻烦,因为事先我们无法判断输入的数据是哪种编码,所以必须靠我们自己写个判断函数。我的方法是根据第一行的输入,如果第一行输入的只有一个数,说明输入是第一种编码;如果是两个数,说明是第二种编码。还有就是代码完全是用c写的,不能像使用c++那用直接使用自带的queue。所以只有靠自己实现了个循环队列,根据题目,队列中的最大个数是不会超过12的,所以自己写队列还是可以接受的,不过就是编码花的时间比较久(汗!!以后直接用c++的queue了,这样省事多了,而且代码还很健壮!!)。

timus_1007_bfs的更多相关文章

随机推荐

  1. python 装饰器学习(decorator)

    最近看到有个装饰器的例子,没看懂, #!/usr/bin/python class decorator(object): def __init__(self,f): print "initi ...

  2. 理解一下单片机的I2C和SPI通信

    应某位网友要求,今天说一下单片机的I2C SPI通信,可能说不清楚,因为这毕竟要做实验才可完全理解. I2C和SPI是两种不同的通信协议. 听到协议,似乎高不可攀,其实协议就是人们定义的一个标准而已, ...

  3. C#中的常见集合类的比较

    一.非泛型集合与泛型集合 非泛型集合:Array.ArrayList.HashTable.Queue.Statck.SortedList 泛型集合:List.Dictionary.Queue.Stac ...

  4. linux-11 基本命令之 -工作期目录切换命令-pwd,cd,

    pwd 命令用于显示当前的工作目录,格式为:pwd[选项] @1.查看当前的工作路径: [root@localhost /]# pwd cd 命令用于切换工作路径 格式为:"cd 目录名称& ...

  5. Apple II DOS 源代码发布

    加州山景城的计算机历史博物馆不仅仅展示硬件,还展示软件.博物馆此前已发布了著名软件MacPaint .Photoshop和APL的源代码,现在它公开了1978年的Apple II DOS源代码.源代码 ...

  6. Android 事件拦截机制一种粗鄙的解释

    对于Android事件拦截机制,相信对于大多数Android初学者是一个抓耳挠腮难于理解的问题.其实理解这个问题并不困难. 首先,你的明白事件拦截机制到底是怎么一回事?这里说的事件拦截机制,指的是对触 ...

  7. C语言结构体-struct

    知识点: 1)结构体的定义. 2)结构体的sizeof. 3)  结构体的指针. 1) 结构体的定义: 在逻辑上有一定关联的多个数据类型做为一整体进行操作的数据结构,它的关键字是struct.下面我将 ...

  8. vCPU估算的几个基本概念

    物理CPU数量:实际服务器插槽上的CPU个数: 核:一块CPU上面能处理数据的芯片组的数量: 超线程:在一个实体芯片组中提供两个逻辑线程: 逻辑CPU数量:物理CPU数量*核*超线程(若支持超线程,该 ...

  9. 运用DebugDiag诊断ASP.Net异常

    Debug Diagnostic Tool (DebugDiag)是用来帮助诊断IIS/COM+等应用假死.性能差.内存泄露及碎片和崩溃等问题的工具. 本文介绍如何运用DebugDiag诊断特定的AS ...

  10. 修复Telerik reporting 在网页中使用时的样式

    在ASP.NET 网页或ASP MVC中嵌入Telerik Reporting时,报表出来的样式是有问题的,按扭的位置错位了. 在页面中引入以下CSS文件可以将报表样式修复从而回到正常的报表样式. . ...