【题译】
通过字符'\'和'/',你可以生成一个小巧的迷宫。迷宫中的路径不会有分叉,因此迷宫中的路径可以形成环,也可以通往迷宫的入口和出口。我们只对环感兴趣。
给你指定一个编程任务,找出迷宫中环的个数,以及所有环当中最长路径的长度。长度通过原文图中所示的灰色方块个数统计求得,在该例子中,最长环的长度为16,共有2个环。
【思路】
由于是倾斜的迷宫(不知道这么说对不对),不能用往常的迷宫遍历来做,需要做一些处理,将斜迷宫转为横竖迷宫,也就是我们熟悉的迷宫。关键就是对字符'/'和字符'\'的处理。字符'\'可表示为
将字符转为3*3的小矩阵,一个圆圈代表迷宫中可以走动的路径,而X标记代表墙壁,不能走到这个位置,对字符'/'的处理也是一样
因此,题目中所给的第一个输入样例可表示为下图
蓝色的圆圈形成环的路径,这样只需沿着上下左右四个方向简单遍历即可。由图中可知共有2个环,最长的环路径包含了48个圆圈,由于圆圈是3*3矩阵内的元素,将48再除回3,可得到最大长度16。
【代码】
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <stack>
#include <queue>
#include <vector>
#include <list>
#include <set>
#include <algorithm>
#define loop_add(i, x1, x2) for (int i = (x1); i <= (x2); i ++)
#define loop_dec(i, x1, x2) for (int i = (x1); i >= (x2); i --)
#define GetMax(a, b) ((a) > (b))? (a) : (b);
#define GetMin(a, b) ((a) < (b))? (a) : (b);
#define EPS 1e-
using namespace std;
bool visit[80*3][80*3];// 标记被访问过的位置
bool map[80*3][80*3];// 简化处理后的迷宫
bool isLoop;// 判断深度优先搜索能否形成一个环
int cnt, maxLength, curLength;// 环的个数,环的最大长度,当前遍历得到的长度
int row, col;// 迷宫的行数、列数
int dirx[] = {0, 1, 0, -1};// x方向的搜索
int diry[] = {-1, 0, 1, 0};// y方向的搜索
bool isOut(int x, int y) {
if (x < 0 || y < 0 || x >= row*3 || y >= col*3)// 是否越界
return true;
else
return false;
}
void dfs(int curx, int cury) {
visit[curx][cury] = true;// 标记为访问过
curLength ++;// 当前步长增加1
loop_add(i, 0, 3) {
int x = curx+dirx[i];
int y = cury+diry[i];
if (isOut(x, y)) {
isLoop = false;//越界了就不可能形成环
return;
}
if (!visit[x][y] && !map[x][y]) {
dfs(x, y);// 继续向下一个方向搜索
}
}
}
int main() {
int t = 1;
while (~scanf("%d%d", &col, &row) && (row || col)) {
maxLength = 0;
cnt = 0;
memset(visit, false, sizeof (visit));
memset(map, false, sizeof (map)); // map数值为false代表该位置可以通行,否则为障碍物
for (int i = 0; i < row*3; i += 3) {
getchar();
for (int j = 0; j < col*3; j += 3) {
char ch = getchar();
if (ch == '\\') // 输入了'\'的符号
map[i][j] = map[i+1][j+1] = map[i+2][j+2] = true;
else if (ch == '/') // 输入了'/'的符号
map[i][j+2] = map[i+1][j+1] = map[i+2][j] = true;
}
}
loop_add(i, 0, 3*row-1) {
loop_add(j, 0, 3*col-1) {
if (!visit[i][j] && !map[i][j]) {
curLength = 0;
isLoop = true;
dfs(i, j);//从坐标(i, j)开始深度优先搜索
if (isLoop) {
maxLength = GetMax(maxLength, curLength);
cnt ++;
}
}
}
}
printf("Maze #%d:\n", t ++);
if (cnt > 0)
printf("%d Cycles; the longest has length %d.\n\n", cnt, maxLength/3);
else
printf("There are no cycles.\n\n");
}
return 0;
}