深度优先搜索——城堡问题

学习了中国大学生mooc,北大周郭炜老师的算法课,开始算法入门

关于课上用深度优先思想实现的“城堡问题”进行整理。

问题

上图是一个城堡的地形图。请你编写一个程序,计算城堡一共有多少房间最大的房间有多大。

城堡被分割成m×n(m≤50,n≤50)个方块,每个方块可以有0~4面墙。

输入

  •   程序从标准输入设备读入数据。
  •   第一行是两个整数,分别是南北向、东西向的方块数
  •   在接下来的输入行里,每个方块用一个数字(0≤p≤50)描述。用一个数字表示方块周围的墙,

                  1表示西墙,2表示北墙,4表示东墙,8表示南墙。  每个方块用代表其周围墙的数字之和表示。

                   城堡的内墙被计算两次,方块(1,1)的南墙同时也是方块(2,1)的北墙.

  •   输入的数据保证城堡至少有两个房间。


输出

  •   城堡的房间数、城堡中最大房间所包括的方块数
  •   结果显示在标准输出设备上。

解题思路

  • 把方块看作是节点,相邻两个方块之间如果没有墙,则在方块之间连一条边,这样城堡就能转换成一个图。
  • 求房间个数,实际上就是在求图中有多少个极大连通子图。
  • 一个连通子图,往里头加任何一个图里的其他点,就会变得不连通,那么这个连通子图就是极大连通子图。(如:(8,5,6)
  • 本质是图的遍历问题

  • 对每一个房间,深度优先搜索,从而给这个房间能够到达的所有位置染色(方格是第几号房间)。

         最后统计一共用了几种颜色,以及每种颜色的数量。
比如
从而一共有5个房间,最大的房间(1)占据9个格子

代码:

#include <iostream>
#include <stack>
#include <cstring>
using namespace std;
int R,C;//行,列数
int rooms [60][60];//每个方块的墙数 
int color[60][60];//方块是否染色过的标记
int maxRoomArea =0, roomNum =0;//最大房间的方格数,房间数目
int roomArea;//正在探索房间的面积
void Dfs(int i, int k){ 
    if(color[i][k]) return;//如果被染色了 ,跳出 
    ++roomArea;// 如果没染色面积+1 
    color [i][k]=roomNum;//染上色 
    //探索相邻的方块是否能走 
    if(( rooms[i][k]&1)==0)Dfs(i,k-1);//如果没有西墙,向西走
    if(( rooms[i][k]&2)==0)Dfs(i-1,k);//如果没有北墙,向北走
    if(( rooms[i][k]&4)==0)Dfs(i,k+1);//如果没有东墙,向东走 
    if(( rooms[i][k]&8)==0)Dfs(i+1,k);//如果没有南墙,向南走
    //数据保障,不必考虑越界 
}
int main (){
     cin >>R>>C;
   for( int i=1;i<=R;++i)
       for(int k=1;k<=C;++k)
            cin >> rooms [i][k];
    memset(color,0, sizeof(color));//标记都未染色 
    for( int i=1;i<=R;++i)
       for(int k=1;k<=C;++k)
            if( !color[i][k]){//判断i行k列方块是否被染色 
                ++roomNum; roomArea=0;//当发现未染色的方块,就找到了一个新的房间 
                Dfs(i,k);//当前roomArea在Dfs中被探索出来了 
                maxRoomArea=max(roomArea, maxRoomArea);//比较最大的房间 
            } 
    cout <<roomNum << endl;
    cout << maxRoomArea << endl;
//复杂度:O(R*C)
}
  

输入

4
7
11 6 11 6 3 10 6
7 9 6 13 5 15 5
1 10 12 7 13 7 5
13 11 10 8 10 12 13

输出

5
9

  

猜你喜欢

转载自www.cnblogs.com/wangyafeidr/p/12497742.html