学习了中国大学生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