迷宫图 用 FloodFill 解决
来源:互联网 发布:netflix推荐算法竞赛 编辑:程序博客网 时间:2024/06/05 16:46
思路:
- int FloodFill(int x, int y) {
- // 首先判断是否出界
- if (x < 0 || x >= h_maze
- || y < 0 || y >= w_maze) {
- return 0;
- }
- //再判断已经扫描过,如果扫描过就退出
- if (maze[x][y] != ' ') {
- return 0;
- }
- // 最后进行下一步的扫描即下一个方格,下个方格的四个方向都要扫描一篇(像泛洪).
- maze[x][y] = '#';
- int sum = 1;
- for (int i = 0; i < 4; ++i) {
- sum += FloodFill(x + CHANGE[i].x, y + CHANGE[i].y);
- }
- return sum;
- }
Description
输入一张迷宫图,全部由 '/'、'\' 组成。
这样,迷宫就变成一个斜线迷宫。
因为输入全为 '/' 、'\' ,因此,这个迷宫将由全部宽度为1的路径组成。
要求输出迷宫中有几个回环,即封闭的路径有几条,其中最长的有多长。
Types
Date Structure :: Graphs
Analysis
经典的斜线迷宫题。
可用 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 数组来映射,好处就是不用扩大原图,时间复杂度相对前两种,常数较低。
Solution
- // UVaOJ 705
- // Slash Maze
- // by A Code Rabbit
- #include <cstdio>
- struct Change {
- int x;
- int y;
- };
- Change CHANGE[] = {
- {-1, 0},
- { 0, -1}, { 0, 1},
- { 1, 0},
- };
- const int LIMITS_W = 1000;
- const int LIMITS_H = 1000;
- int num_case = 0;
- char maze[LIMITS_H][LIMITS_W];
- int w, h;
- int w_maze, h_maze;
- void EnlargeAndSave(int x, int y, char ch);
- int FloodFill(int x, int y);
- int main() {
- while (scanf("%d%d", &w, &h)) {
- getchar();
- // Exit.
- if (!w && !h) {
- break;
- }
- // Inputs.
- for (int i = 0; i < h; ++i) {
- for (int j = 0; j < w; ++j) {
- EnlargeAndSave(i, j, getchar());
- }
- getchar();
- }
- w_maze = w * 3;
- h_maze = h * 3;
- // DFS: Remove grids of the maze without cycles.
- for (int i = 0; i < h_maze; ++i) {
- FloodFill(i, 0);
- FloodFill(i, w_maze - 1);
- }
- for (int i = 0; i < w_maze; ++i) {
- FloodFill(0, i);
- FloodFill(h_maze - 1, i);
- }
- // DFS: Search and compete the maze with cycles.
- int max = 0;
- int sum = 0;
- for (int i = 0; i < h_maze; ++i) {
- for (int j = 0; j < w_maze; ++j) {
- int result = FloodFill(i, j) / 3;
- if (result) {
- max = result > max ? result : max;
- ++sum;
- }
- }
- }
- // Outputs.
- printf("Maze #%d:\n", ++num_case);
- if (sum) {
- printf("%d Cycles; the longest has length %d.\n", sum, max);
- } else {
- printf("There are no cycles.\n");
- }
- printf("\n");
- }
- return 0;
- }
- void EnlargeAndSave(int x, int y, char ch) {
- for (int i = 0; i < 3; ++i) {
- for (int j = 0; j < 3; ++j) {
- maze[x * 3 + i][y * 3 + j] = ' ';
- }
- }
- if (ch == '/') {
- maze[x * 3][y * 3 + 2] = '#';
- maze[x * 3 + 1][y * 3 + 1] = '#';
- maze[x * 3 + 2][y * 3] = '#';
- } else {
- maze[x * 3][y * 3] = '#';
- maze[x * 3 + 1][y * 3 + 1] = '#';
- maze[x * 3 + 2][y * 3 + 2] = '#';
- }
- }
- int FloodFill(int x, int y) {
- // Exit.
- if (x < 0 || x >= h_maze
- || y < 0 || y >= w_maze) {
- return 0;
- }
- if (maze[x][y] != ' ') {
- return 0;
- }
- // Continue.
- maze[x][y] = '#';
- int sum = 1;
- for (int i = 0; i < 4; ++i) {
- sum += FloodFill(x + CHANGE[i].x, y + CHANGE[i].y);
- }
- return sum;
- }
2. 四分法
- // UVaOJ 705
- // Slash Maze
- // by A Code Rabbit
- #include <cstdio>
- struct Change {
- int x;
- int y;
- };
- Change STRAIGHT_CHANGE[] = {
- {-1, 0},
- { 0, -1}, { 0, 1},
- { 1, 0},
- };
- Change SLASH_CHANGE[] = {
- {-1, -1}, {-1, 1},
- { 1, -1}, { 1, 1},
- };
- const int LIMITS_W = 500;
- const int LIMITS_H = 500;
- int num_case = 0;
- char maze[LIMITS_H][LIMITS_W];
- int w, h;
- int w_maze, h_maze;
- void EnlargeAndSave(int x, int y, char ch);
- bool canArrive(int x, int y, Change change);
- int FloodFill(int x, int y);
- int main() {
- while (scanf("%d%d", &w, &h)) {
- getchar();
- // Exit.
- if (!w && !h) {
- break;
- }
- // Inputs.
- for (int i = 0; i < h; ++i) {
- for (int j = 0; j < w; ++j) {
- EnlargeAndSave(i, j, getchar());
- }
- getchar();
- }
- w_maze = w * 2;
- h_maze = h * 2;
- // DFS: Remove grids of the maze without cycles.
- for (int i = 0; i < h_maze; ++i) {
- FloodFill(i, 0);
- FloodFill(i, w_maze - 1);
- }
- for (int i = 0; i < w_maze; ++i) {
- FloodFill(0, i);
- FloodFill(h_maze - 1, i);
- }
- // DFS: Search and compete the maze with cycles.
- int max = 0;
- int sum = 0;
- for (int i = 0; i < h_maze; ++i) {
- for (int j = 0; j < w_maze; ++j) {
- int result = FloodFill(i, j);
- if (result) {
- max = result > max ? result : max;
- ++sum;
- }
- }
- }
- // Outputs.
- printf("Maze #%d:\n", ++num_case);
- if (sum) {
- printf("%d Cycles; the longest has length %d.\n", sum, max);
- } else {
- printf("There are no cycles.\n");
- }
- printf("\n");
- }
- return 0;
- }
- void EnlargeAndSave(int x, int y, char ch) {
- maze[x * 2][y * 2] = ch == '/' ? ' ' : '#';
- maze[x * 2][y * 2 + 1] = ch == '/' ? '#' : ' ';
- maze[x * 2 + 1][y * 2] = ch == '/' ? '#' : ' ';
- maze[x * 2 + 1][y * 2 + 1] = ch == '/' ? ' ' : '#';
- }
- bool canArrive(int x, int y, Change change) {
- int x_after_change = x % 2 + change.x;
- int y_after_change = y % 2 + change.y;
- if (0 <= x_after_change && x_after_change < 2
- && 0 <= y_after_change && y_after_change < 2) {
- return false;
- } else
- if ((x_after_change < 0 || x_after_change >= 2)
- && (y_after_change < 0 || y_after_change >= 2)) {
- return false;
- } else {
- return true;
- }
- printf("\n");
- }
- int FloodFill(int x, int y) {
- // Exit.
- if (x < 0 || x >= h_maze
- || y < 0 || y >= w_maze) {
- return 0;
- }
- if (maze[x][y] != ' ') {
- return 0;
- }
- // Continue.
- maze[x][y] = '.';
- int sum = 1;
- for (int i = 0; i < 4; ++i) {
- sum += FloodFill(x + STRAIGHT_CHANGE[i].x, y + STRAIGHT_CHANGE[i].y);
- }
- for (int i = 0; i < 4; ++i) {
- if (canArrive(x, y, SLASH_CHANGE[i])) {
- sum += FloodFill(x + SLASH_CHANGE[i].x, y + SLASH_CHANGE[i].y);
- }
- }
- return sum;
- }
- // UVaOJ 705
- // Slash Maze
- // by A Code Rabbit
- #include <cstdio>
- #include <cstring>
- enum Direction {
- UP = 0,
- DOWN = 1,
- LEFT = 2,
- RIGHT = 3,
- };
- struct Change {
- int x;
- int y;
- };
- const Direction DIRECTION[] = {
- UP,
- DOWN,
- LEFT,
- RIGHT,
- };
- // Form four directions what are UP, DOWN, LEFT, RIGHT.
- const Change CHANGE[] = {
- {-1, 0},
- { 1, 0},
- { 0, -1},
- { 0, 1},
- };
- // Form four directions what are UP, DOWN, LEFT, RIGHT.
- const Direction REFLEX_SLASH[] = {
- LEFT,
- RIGHT,
- UP,
- DOWN,
- };
- const Direction REFLEX_BACKSLASH[] = {
- RIGHT,
- LEFT,
- DOWN,
- UP,
- };
- const int LIMITS_W = 100;
- const int LIMITS_H = 100;
- int num_case = 0;
- char maze[LIMITS_W][LIMITS_H];
- int w, h;
- bool is_visited[LIMITS_W][LIMITS_H][4];
- Direction Opposite(Direction direction);
- int FloodFill(int x, int y, Direction direction);
- int main() {
- while (scanf("%d%d", &w, &h)) {
- getchar();
- // Exit.
- if (!w && !h) {
- break;
- }
- // Inputs.
- for (int i = 0; i < h; ++i) {
- gets(maze[i]);
- }
- // DFS: Remove grids of the maze without cycles.
- memset(is_visited, false, sizeof(is_visited));
- for (int i = 0; i < h; ++i) {
- FloodFill(i, 0, LEFT);
- FloodFill(i, w - 1, RIGHT);
- }
- for (int i = 0; i < w; ++i) {
- FloodFill(0, i, UP);
- FloodFill(h - 1, i, DOWN);
- }
- //Show();
- // DFS: Search and compete the maze with cycles.
- int max = 0;
- int sum = 0;
- for (int i = 0; i < h; ++i) {
- for (int j = 0; j < w; ++j) {
- for (int k = 0; k < 4; k++) {
- int result = FloodFill(i, j, DIRECTION[k]);
- if (result) {
- max = result > max ? result : max;
- ++sum;
- }
- }
- }
- }
- // Outputs.
- //Show();
- printf("Maze #%d:\n", ++num_case);
- if (sum) {
- printf("%d Cycles; the longest has length %d.\n", sum, max);
- } else {
- printf("There are no cycles.\n");
- }
- printf("\n");
- }
- return 0;
- }
- Direction Opposite(Direction direction) {
- if (direction == LEFT) {
- return RIGHT;
- } else
- if (direction == RIGHT) {
- return LEFT;
- } else
- if (direction == UP) {
- return DOWN;
- } else
- if (direction == DOWN) {
- return UP;
- }
- }
- int FloodFill(int x, int y, Direction direction) {
- // Exit.
- if (x < 0 || x >= h
- || y < 0 || y >= w) {
- return 0;
- }
- if (is_visited[x][y][direction]) {
- return 0;
- }
- is_visited[x][y][direction] = true;
- // Continue.
- Direction direction_leave;
- if (maze[x][y] == '/') {
- direction_leave = REFLEX_SLASH[direction];
- } else {
- direction_leave = REFLEX_BACKSLASH[direction];
- }
- is_visited[x][y][direction_leave] = true;
- return 1 + FloodFill(x + CHANGE[direction_leave].x,
- y + CHANGE[direction_leave].y,
- Opposite(direction_leave));
- }
- 迷宫图 用 FloodFill 解决
- floodfill
- floodfill
- floodfill
- 用BFS解决迷宫问题
- 用栈解决迷宫问题
- 用栈解决迷宫问题
- 好用的算法,FloodFill
- 用C语言解决迷宫问题
- 用栈和递归解决迷宫问题
- 连通图_连通分量FloodFill
- C++ 解决迷宫问题
- c解决迷宫问题
- 栈解决迷宫求解
- 迷宫问题bfs解决
- OOP解决迷宫问题
- java解决迷宫问题
- 用纯C语言解决迷宫问题,简洁易懂
- 如何利用dex2jar反编译APK
- java——XML与java对象装换
- android开发之AlertDialog点击按钮之后不消失
- gdb 查看变量和内存
- Android判断Service是否运行
- 迷宫图 用 FloodFill 解决
- Linux shell学习笔记
- 首款Unreal Engine 4引擎制作手机游戏曝光
- gcd
- SqlServer 游标选项说明及测试
- Win8 下重装 Chrome 浏览器遇到"糟糕!安装失败。错误代码:0xa0430721。"错误的解决
- 虚幻4引擎可让手机游戏媲美PC游戏画面
- a different object with the same identifier value was already associated with the session
- iOS设置边框、圆角