题目意思:给定一个地图,由'\'和'/'组成,要求里面能够构成的环的个数,以及最大的环的步数。
解题思路:对于这类的题目,我们可以利用小化大的思想,我们利用一个比地图大两倍的数组来存储这个地图(四格思想),对于'/',存为1 '\'存为-1,然后我们就可以像在平面上面一样直接dfs,还有对于一个环,它的各个步数肯定都是不能有和边界接触的,那么我们用一个flag来标记是否是环即可求出。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 200;
int w , h , Max , step , flag , sum;
//Max求出最大的环的步数 step是用来计算每一次搜索的步数 flag判断是否有出界 sum存储最大的环的个数
int num[MAXN][MAXN];//把'\'和'/'转换后的值存储在这个数组
int vis[MAXN][MAXN];//标记是否走过
int dir[8][2] = {{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};//方向数组
//深搜
void dfs(int i , int j){
int k;
for(k = 0 ; k < 8 ;k++){
if(i+dir[k][0] < 0 || i+dir[k][0] >= 2*h){
flag = 0 ; continue;//如果出界就把flag记为0
}
if(j+dir[k][1] <0 || j+dir[k][1] >= 2*w){
flag = 0; continue;//如果出界就把flag记为0
}
if(num[i+dir[k][0]][j+dir[k][1]] != 0)//如果有数值则是不能走
continue;
if(vis[i+dir[k][0]][j+dir[k][1]] != 0)//如果走过的或者是原点则不能走
continue;
if(num[i+dir[k][0]][j+dir[k][1]] == 0 && vis[i+dir[k][0]][j+dir[k][1]] == 0 ){//满足数值为0且没有走过继续搜索 (记住我按顺时针给搜索方向标记了数字0~7)
if(k == 1){
if(num[i-1][j] == 1 && num[i][j+1] == 1){
vis[i-1][j+1] = 1;
step++;//对应加一个步数
dfs(i-1 , j+1);
}
}
else if(k == 5){
if(num[i+1][j]== 1 && num[i][j-1] == 1){
vis[i+1][j-1] = 1;
step++;;//对应加一个步数
dfs(i+1 , j-1);
}
}
else if(k == 3){
if(num[i][j+1] == -1 && num[i+1][j] == -1){
vis[i+1][j+1] = 1;
step++;;//对应加一个步数
dfs(i+1 , j+1);
}
}
else if(k == 7){
if(num[i-1][j] == -1 && num[i][j-1] == -1){
vis[i-1][j-1] = 1;
step++;;//对应加一个步数
dfs(i-1 , j-1);
}
}
else{
vis[i+dir[k][0]][j+dir[k][1]] = 1;
step++;;//对应加一个步数
dfs(i+dir[k][0] , j+dir[k][1]);
}
}
}
}
//处理问题函数
void solve(){
int i , j;
memset(vis , 0 , sizeof(vis));//初始化
Max = 0;sum = 0;
for(i = 0 ; i < 2*h ; i++){
for(j = 0 ; j < 2*w ; j++){
if(num[i][j] == 0 && vis[i][j] == 0){
step = 1;flag = 1;//初始化为1
vis[i][j] = -1;//先标价为-1
dfs(i , j);//搜索
vis[i][j] = 1;//在从新标记为1
if(flag){//如果是环则sum加加,判断最大的Max
sum++;
if(Max < step)
Max = step;
}
}
}
}
}
//主函数
int main(){
int i , j , t = 1;
char ch;
while(scanf("%d%d%*c" , &w , &h) &&w &&h){ //读入判断
memset(num , 0 , sizeof(num));
for(i = 0 ; i < h ;i++){
for(j = 0 ; j < w ; j++){
scanf("%c" , &ch);
if(ch == '\\'){//如果是‘\’化为-1
num[2*i][j*2] = -1;
num[2*i+1][j*2+1] = -1;
}
if(ch == '/'){//如果是'/'化为1
num[2*i+1][2*j] = 1;
num[2*i][2*j+1] = 1;
}
}
getchar();
}
solve();
printf("Maze #%d:\n" ,t);
if(sum).
printf("%d Cycles; the longest has length %d.\n\n" ,sum ,Max);
else
printf("There are no cycles.\n\n");
t++;
}
return 0;
}