深度优先搜索-城堡问题

城堡问题:
右图是一个城堡的地形图。请你编写一个程序,计算城堡一共有多少房间,
最大的房间有多大。城堡被分割成m×n(m≤50,n≤50)个方块,每个方块可
以有0~4面墙。

输入
 程序从标准输入设备读入数据。
 第一行是两个整数,分别是南北向、东西向的方块数。
 在接下来的输入行里,每个方块用一个数字(0≤p≤50)描述。用一个数
字表示方块周围的墙, 1表示西墙, 2表示北墙, 4表示东墙, 8表示南
墙。 每个方块用代表其周围墙的数字之和表示。 城堡的内墙被计算两
次,方块(1,1)的南墙同时也是方块(2,1)的北墙。
 输入的数据保证城堡至少有两个房间。
 输出
 城堡的房间数、城堡中最大房间所包括的方块数。
 结果显示在标准输出设备上。

 样例输入
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

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

对每一个房间,深度优先搜索,从而给这个房间能够到达的所有位置染色。
最后统计一共用了几种颜色,以及每种颜色的数量。
 比如
1 1 2 2 3 3 3
1 1 1 2 3 4 3
1 1 1 5 3 5 3
1 5 5 5 5 5 3
 从而一共有5个房间,最大的房间(1)占据9个格子

python算法实现:

 1 # 当前房屋的值
 2 rooms = []
 3 # 方块是否染色过的标记
 4 color = []
 5 """
 6 [[0, 0, 0, 0, 0, 0, 0, 0],
 7 [0, 1, 1, 2, 2, 3, 3, 3],
 8 [0, 1, 1, 1, 2, 3, 4, 3],
 9 [0, 1, 1, 1, 5, 3, 5, 3],
10 [0, 1, 5, 5, 5, 5, 5, 3]]
11 """
12 # 最大的房间面积,当前房间面积,当前房间数量
13 maxRoomArea, roomArea, roomNum = 0, 0, 0
14 
15 
16 def Dfs(i, j):
17     global color, roomArea, roomNum, rooms
18     # 说明该点已经访问过
19     if color[i][j] != 0:
20         return
21     roomArea = roomArea + 1
22     # 标记该房间是哪一组的
23     color[i][j] = roomNum
24     # 向西走 1-0001
25     if (rooms[i][j] & 1) == 0:
26         Dfs(i, j-1)
27     # 向北 2-0010
28     if (rooms[i][j] & 2) == 0:
29         Dfs(i-1, j)
30     # 向东 4-0100
31     # 比如11-1011,与4的二进制做与运算,计算结果是0,说明东墙是空的,可以走
32     if (rooms[i][j] & 4) == 0:
33         Dfs(i, j+1)
34     # 向南 8-1000
35     if (rooms[i][j] & 8) == 0:
36         Dfs(i+1, j)
37     return
38 
39 
40 def main():
41     global rooms, color, roomNum, roomArea, maxRoomArea
42     tempList = []
43     # r-行,c-列
44     r, c = map(int, input().split())
45     # 从把每个房间的值储存从位置1开始,方便后续计算
46     rooms = [[0 for j in range(c)] for i in range(r+1)]
47     color = [[0 for j in range(c+1)] for i in range(r+1)]
48     # 初始化二维列表
49     for i in range(1, r+1):
50         tempList = list(map(int, input().split()))
51         # 因为输入的数有7个,为了计算方便,凑够8列,所以在0位置补个0
52         tempList.insert(0, 0)
53         rooms[i] = tempList
54     # [[0, 0, 0, 0, 0, 0, 0],
55     #  [0, 11, 6, 11, 6, 3, 10, 6],
56     #  [0, 7, 9, 6, 13, 5, 15, 5],
57     #  [0, 1, 10, 12, 7, 13, 7, 5],
58     #  [0, 13, 11, 10, 8, 10, 12, 13]]
59     for i in range(1, r+1):
60         for j in range(1, c+1):
61             # 遍历所有没有访问过的点
62             if color[i][j] == 0:
63                 # 每次访问新的点,说明该点与访问过的点是不连通的,相互不能走通
64                 # 不是同一个roomNum,因此最大面积置0,重新开始计算
65                 roomArea = 0
66                 # 因为不是同一组,房间号在原来的基础上新增1,以表示不同的房间号
67                 roomNum = roomNum + 1
68                 Dfs(i, j)
69                 maxRoomArea = max(roomArea, maxRoomArea)
70     print("一共有%d个房间,最大的房间面积%d" % (roomNum, maxRoomArea))
71     return 0
72 
73 
74 if __name__ == '__main__':
75     main()

 

posted @ 2020-07-02 18:09  StudyNLP  阅读(212)  评论(0编辑  收藏  举报