网格-递归作业 城堡问题
描述 | |
图1是一个城堡的地形图。请你编写一个程序,计算城堡一共有多少房间,最大的房间有多大。城堡被分割成m*n(m≤50,n≤50)个方块,每个方块可以有0~4面墙。 |
|
关于输入 | |
程序从标准输入设备读入数据。第一行是两个整数,分别是南北向、东西向的方块数。在接下来的输入行里,每个方块用一个数字(0≤p≤50)描述。用一个数字表示方块周围的墙,1表示西墙,2表示北墙,4表示东墙,8表示南墙。每个方块用代表其周围墙的数字之和表示。城堡的内墙被计算两次,方块(1,1)的南墙同时也是方块(2,1)的北墙。输入的数据保证城堡至少有两个房间。 | |
关于输出 | |
输出分为两行。城堡的房间数、城堡中最大房间所包括的方块数。结果显示在标准输出设备上。 | |
例子输入 | |
4 7
|
|
例子输出 | |
5
|
代码:
1 //城堡问题 2 // 3 //2019-11-11 4 #include<iostream> 5 #include<cstring> 6 using namespace std; 7 int a[51][51]; 8 int visited[51][51]; 9 int m, n; 10 bool isr(int x, int y){ //判断a[x][y]位置是否合法 11 if(x>=1&&x<=m&&y>=1&&y<=n&&!visited[x][y]) 12 return true; 13 return false; 14 } 15 16 int dfs(int x, int y, int ans){ 17 visited[x][y]=ans; //给这个房间做上标记 18 if(!(a[x][y]&1)&&isr(x,y-1)) //没有西墙,注意这个判断技巧,因为用二进制压缩的数据 19 dfs(x,y-1,ans); 20 if(!(a[x][y]&2)&&isr(x-1,y)) //没有北墙 21 dfs(x-1,y,ans); 22 if(!(a[x][y]&4)&&isr(x,y+1)) //没有东墙 23 dfs(x,y+1,ans); 24 if(!(a[x][y]&8)&&isr(x+1,y)) //没有南墙 25 dfs(x+1,y,ans); 26 } 27 28 int main(){ 29 cin>>m>>n; //m*n个方格 30 int i, j; 31 for(i = 1; i <= m; i++) 32 for(j = 1; j <= n; j++) 33 cin>>a[i][j]; 34 int ans = 0; //用于记房间数 35 int maxx = 0; //用于记最大的房间 36 for(i = 1; i <= m; i++) 37 for(j = 1; j <= n; j++) 38 if(!visited[i][j]){ 39 ans++; //找到一个房间 40 dfs(i,j,ans); //更新房间容量 41 } 42 int room[3000]; //用来记房间数 43 memset(room,0,sizeof(room)); 44 for(i = 1; i <= m; i++) 45 for(j = 1; j <= n; j++) 46 if(visited[i][j]){ 47 room[visited[i][j]]++; 48 } 49 for(i = 0; i < 3000; i++) 50 maxx = max(maxx, room[i]); //找最大值 51 cout<<ans<<endl<<maxx; 52 return 0; 53 }
备注:这道题有一点巧妙的地方在于用二进制压缩了每个房间哪个方向有墙的信息。判断的时候用与&运算就可以了。
另外就是在dfs的过程中将房间编上号,每一次dfs有不同的标志,最后再从头到尾扫一遍来找最大的房间。(用dfs的参数step是不行的)