OpenJudge 2.5-1817&&166 城堡问题(The Castle)

来源:互联网 发布:百度云加速软件 编辑:程序博客网 时间:2024/09/21 09:26
Description
1   2   3   4   5   6   7     ############################# 1 #   |   #   |   #   |   |   #   #####---#####---#---#####---# 2 #   #   |   #   #   #   #   #   #---#####---#####---#####---# 3 #   |   |   #   #   #   #   #   #---#########---#####---#---# 4 #   #   |   |   |   |   #   #   #############################           (图 1)   #  = Wall      |  = No wall   -  = No wall


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

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 

Sample Output

59

      拿到这道题之后第一步想到的就是想办法将那些数字先转化成前面的图或者通过标记达到构图目的,这样题目的做法就与Lake Counting是一样的,只是要多统计一个数据:最大房间的方块数。而题目给了一个方块上的墙所代表的数字和,想要达到图的目的就得知道哪些地方有墙,哪些地方没有。那么问题就是如何将一个方块上的数分离开来,从而得知哪些地方有墙呢?

       一开始我的思路是从角落开始搜,确定哪堵墙没有再挨着挨着往里拓展,确定哪些墙没有(用四面墙之和(当然有的地方肯定没有墙的不用加)减去它本身,结果的值就是没有的墙),后面还没开始操作就受到了一些启发(这里是重难点):用来表示的数字:1,2,4,8分别是2^0,2^1,2^2,2^3,联想到二进制,可以用方块四面墙的和分别与上1,2,4,8,如果为1,就有这面墙,否则没有。如果还有点儿懵,那再阐述一下:二进制数转化为十进制数是用每一位上的数分别乘2^0,2^1,2^2

,2^3……,再加起来,而这里的墙分别为1,2,4,8,所以方块的数恰好为2^0,2^1,2^2,2^3分别乘上自己二进制数各个位数的和,如果加了那个数,那个数对应的位上就为1(二进制中),就有那堵墙,而判断位上是1还是0,可以用位与运算分别与上1,2,4,8     1(2)=0001,2(2)=0010,4(2)=0100,8(2)=1000,只有该位上是1时,与之相与才会为1,否则为0

    于是,我们就可以标记的时候用三维数组标记(增加一个是否有墙),做法与Lake Counting是一样的

    奉上代码:

      

#include<cstdio>int r,c,map[55][55],xx[4]={0,1,0,-1},yy[4]={1,0,-1,0}; bool mark[55][55][5],ma[55][55];int sum,ans,s;bool check(int x,int y){if(x>=0&&x<r&&y>=0&&y<c) return 1;return 0;}void dfs(int x,int y){if(s>ans) ans=s;for(int i=0;i<4;i++)if(check(x+xx[i],y+yy[i])&&!ma[x+xx[i]][y+yy[i]]&&!mark[x+xx[i]][y+yy[i]][i]){ma[x+xx[i]][y+yy[i]]=1;s++;dfs(x+xx[i],y+yy[i]);}}int main(){scanf("%d %d",&r,&c);for(int i=0;i<r;i++)for(int j=0;j<c;j++){scanf("%d",&map[i][j]);if(map[i][j]&1) mark[i][j][0]=1;if(map[i][j]&2) mark[i][j][1]=1;if(map[i][j]&4) mark[i][j][2]=1;if(map[i][j]&8) mark[i][j][3]=1;}for(int i=0;i<r;i++)for(int j=0;j<c;j++)if(!ma[i][j]){ma[i][j]=1;sum++;s=1;dfs(i,j);}printf("%d\n%d",sum,ans);}

题外话:这道题英文和中文是一样的,倒是不用翻译