Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1436516
  • 博文数量: 241
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 2253
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-11 22:27
个人简介

--

文章分类

全部博文(241)

文章存档

2021年(3)

2019年(6)

2018年(1)

2017年(9)

2016年(21)

2015年(50)

2014年(125)

2013年(26)

我的朋友

分类: C/C++

2014-03-17 15:39:37

1、题目简述:

在迷宫中找出最长环路的长度,不是找到出路。

详细描述:

迷宫是由一系列方格组成一个矩形区域,下图是一个 4 * 6 的迷宫 

每个方格中都有一条红色的斜线(/或者\),这是墙,无法通过。灰线不是墙,可自由跨越。 

在迷宫内,只能在相邻的(有公共边的才算相邻,公共顶点不算)三角形的区域之间相互移动。左上角灰色三角形,就是一个区域,从这个区域,可以移动到下面黄色三角形区域中。 

不能越界,只能在大的矩形范围内移动。左边紫色这种移动方式,是不允许的。 

可以看到,中间蓝色的分别是两条环路,环路长度指的是走完这条环路需要走过的三角区域个数,两条环路的长度分别是16和4;绿色的不是一条环路。

请实现如下接口

/* 功能:找出一个迷宫中的最长环路长度,以及总的环路个数

 * 输入:存放迷宫信息的记事本文件路径,该程序从文件中读取迷宫信息。该文件格式后面会说明

 * 输出:CycleCount,环路个数,上面的迷宫,CycleCount为2

* 返回:最长环路长度,上面的迷宫,应返回16.如果没有环路,返回-1.

 */

int FindLongestCycle(constchar* mazefile, int*CycleCount)

{

    /* 请实现*/

    return 0;

迷宫信息:

本题例子中的迷宫以下面文本格式保存。其中斜线,则表示对应方格中的墙。斜线之间无空格。左边的字符串中的斜线和右边图画中的墙一一对应。

随题目附带的两个用例,在testcase目录下。

每行结束以回车(”\r\n”)收尾,没有多余的空格。

最后一行结束,没有回车。

解题时,无需检查该文件格式,由用例保证格式正确。

 

约束:

环路都是简单环路。即除了第一个顶点和最后一个顶点外,其余顶点不重复出现的环路。不会有“8”字形,“6”字型这样的环路。

迷宫宽和高不超过50,宽和高均大于1.

每个格子里都有一堵墙(也就是都会被填进一个斜线),不会出现空格子;

墙只有两种(/ 和 \),不会有其他类型。

2、解题思路:
http://blog.csdn.net/ra_winding/article/details/7724290

经典的斜线迷宫题。

可用 FloodFill 解决。

首先知道,没有封闭的路径,必然将通往图的外面。

所以只要从图的边界开始 FloodFill,把不满足条件的排除后。

再对每一个点去 FloodFill 即可求出所要的解。

而对于斜线的处理,有三种方法:

1. 九分法:将所有的格子都扩大成 9 * 9 的格子,例如

‘/’ 就会变成

然后只要用普通的 FloodFill 对每格上下左右四个方向的 DFS 就可以。


2. 四分法:将所有的格子扩大成 4 * 4 的格子,例如

‘/’ 就会变成

然后依然是对每个格子向八个方向 FloodFill ,但是要注意,在 2 * 2 格子中的某点向周围Flood 的时候,只能到达上下左右的 2 * 2格子。

反之如果 FloodFill 后依然在原先的 2 * 2格子,或者对角线方向的 2 * 2 格子的,将会是穿过了 '/' 的非法情况,需要排除掉。


3. 光线反射法:模拟一条光线在迷宫中照射,继续看图:

对于每个格子,光线可能从四个方向射进来。

在 FloodFill 的时候,判断光线来的方向,找到下一个 FloodFill 的格子即可。

三种方法,第一种较为简单,但是要将原图长宽各扩大三倍,得到一张原图九倍大的新图。

而第二种方法,只要将原图扩大四倍,但是要判断要FloodFill的格子是否可以FloodFill。

而第三种方法,较为复杂,对光线进来的四个方向都要判断反射出去的方向,可以用一个 enum 配合 const 数组来映射,好处就是不用扩大原图,时间复杂度相对前两种,常数较低。


3、代码

点击(此处)折叠或打开

  1. #include "Maze.h"

  2. /* 功能:找出一个迷宫中的最长环路以及环路个数
  3.  * 输入:存放迷宫信息的记事本文件路径,该程序从文件中读取迷宫信息。
  4.  * 输出:CycleCount,环路个数
  5.  * 返回:最长环路长度,如果没有环路,返回-1.
  6.  */

  7. #include <cstdio>
  8. #include <cstring>


  9. enum Direction {
  10.     UP = 0,
  11.     DOWN = 1,
  12.     LEFT = 2,
  13.     RIGHT = 3,
  14. };

  15. struct Change {
  16.     int x;
  17.     int y;
  18. };

  19. const Direction DIRECTION[] = {
  20.     UP,
  21.     DOWN,
  22.     LEFT,
  23.     RIGHT,
  24. };
  25. // Form four directions what are UP, DOWN, LEFT, RIGHT.
  26. const Change CHANGE[] = {
  27.     {-1, 0},
  28.     { 1, 0},
  29.     { 0, -1},
  30.     { 0, 1},
  31. };

  32. // Form four directions what are UP, DOWN, LEFT, RIGHT.
  33. const Direction REFLEX_SLASH[] = {
  34.     LEFT,
  35.     RIGHT,
  36.     UP,
  37.     DOWN,
  38. };
  39. const Direction REFLEX_BACKSLASH[] = {
  40.     RIGHT,
  41.     LEFT,
  42.     DOWN,
  43.     UP,
  44. };

  45. const int LIMITS_W = 100;
  46. const int LIMITS_H = 100;

  47. int num_case = 0;

  48. char maze[LIMITS_W][LIMITS_H];
  49. int w, h;

  50. bool is_visited[LIMITS_W][LIMITS_H][4];

  51. Direction Opposite(Direction direction);
  52. int FloodFill(int x, int y, Direction direction);

  53. Direction Opposite(Direction direction) {
  54.     if (direction == LEFT) {
  55.         return RIGHT;
  56.     } else
  57.     if (direction == RIGHT) {
  58.         return LEFT;
  59.     } else
  60.     if (direction == UP) {
  61.         return DOWN;
  62.     } else
  63.     if (direction == DOWN) {
  64.         return UP;
  65.     }
  66. }

  67. int FloodFill(int x, int y, Direction direction) {
  68.     // Exit.
  69.     if (x < 0 || x >= h
  70.      || y < 0 || y >= w) {
  71.         return 0;
  72.     }
  73.     if (is_visited[x][y][direction]) {
  74.         return 0;
  75.     }
  76.     is_visited[x][y][direction] = true;
  77.     // Continue.
  78.     Direction direction_leave;
  79.     if (maze[x][y] == '/') {
  80.         direction_leave = REFLEX_SLASH[direction];
  81.     } else {
  82.         direction_leave = REFLEX_BACKSLASH[direction];
  83.     }
  84.     is_visited[x][y][direction_leave] = true;
  85.     return 1 + FloodFill(x + CHANGE[direction_leave].x,
  86.                          y + CHANGE[direction_leave].y,
  87.                          Opposite(direction_leave));
  88. }

  89. int FindLongestCycle(const char* mazefile, int *CycleCount)
  90. {

  91.     if (mazefile == NULL || NULL == CycleCount)
  92.     {
  93.         return -1;
  94.     }
  95.     int i = 0;
  96.     FILE* pFile = fopen(mazefile,"r");
  97.     while (fgets(maze[i],LIMITS_W,pFile) != NULL)
  98.     {
  99.         i++;
  100.     }
  101.     fclose(pFile);
  102.     h = i;
  103.     w = strlen(maze[0])-1;

  104.     // DFS: Remove grids of the maze without cycles.
  105.     memset(is_visited, false, sizeof(is_visited));
  106.     for (int i = 0; i < h; ++i)
  107.     {
  108.         FloodFill(i, 0, LEFT);
  109.         FloodFill(i, w - 1, RIGHT);
  110.     }
  111.     for (int i = 0; i < w; ++i)
  112.     {
  113.         FloodFill(0, i, UP);
  114.         FloodFill(h - 1, i, DOWN);
  115.     }
  116.     //Show();
  117.     // DFS: Search and compete the maze with cycles.
  118.     int max = 0;
  119.     int sum = 0;
  120.     for (int i = 0; i < h; ++i)
  121.     {
  122.         for (int j = 0; j < w; ++j)
  123.         {
  124.             for (int k = 0; k < 4; k++)
  125.             {
  126.                 int result = FloodFill(i, j, DIRECTION[k]);
  127.                 if (result)
  128.                 {
  129.                     max = result > max ? result : max;
  130.                     ++sum;
  131.                 }
  132.             }
  133.         }
  134.     }
  135.     // Outputs.
  136.     if (sum)
  137.     {
  138.         printf("%d Cycles; the longest has length %d.\n", sum, max);
  139.         *CycleCount = sum;
  140.         return max;
  141.     }
  142.     else
  143.     {
  144.         return -1;
  145.     }
  146. }

阅读(3049) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~