城堡问题

来源:互联网 发布:身份证图像识别 java 编辑:程序博客网 时间:2024/06/02 17:23

1817:城堡问题

P.S.如果有需要英文版的同学轻点英文版,需要源代码的同学轻点源代码。
总时间限制: 1000ms 内存限制: 65536kB
描述

      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面墙。

输入

程序从标准输入设备读入数据。第一行是两个整数,分别是南北向、东西向的方块数。在接下来的输入行里,每个方块用一个数字(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
来源
1164

【代码】

状态: Accepted

#include<iostream>  #include<cstdio>  #include<cstring>  using namespace std;  int m,n,ans,cnt,bigest; bool flag[100][100],q[100][100][4];  int map[105][105];  int wayr[4]={0,1,0,-1},wayc[4]={1,0,-1,0}; bool check(int a,int b,int x) {      if(a<m&&b<n&&a>=0&&b>=0&&q[a][b][x]&&!flag[a][b]) return 1;      return 0;  }  void dfs(int y,int c) //似于递归 {      for(int i=0;i<4;i++)//四种走法        if(check(y+wayr[i],c+wayc[i],i))          {              flag[y+wayr[i]][c+wayc[i]]=1;              cnt++;  //如果走得通,房间数+1,且标记            dfs(y+wayr[i],c+wayc[i]);              }  //不断递归,到最后cnt就为最大房间数}  int main()  {      scanf("%d%d",&m,&n);      for(int l=0;l<m;l++)        for(int j=0;j<n;j++)          {              scanf("%d",&map[l][j]);              if(!(map[l][j]&1)) q[l][j][0]=1;  //判断走不走得通            if(!(map[l][j]&2)) q[l][j][1]=1;  //也是有没有墙            if(!(map[l][j]&4)) q[l][j][2]=1;  //i行j列的方块,0表示西墙,1表示北墙,2表示东墙,3表示南墙。            if(!(map[l][j]&8)) q[l][j][3]=1;          }      for(int l=0;l<m;l++)         for(int j=0;j<n;j++)              if(!flag[l][j]) //判断走没走过            {                  flag[l][j]=1; //标记                cnt=1;//房间的包括的方块数(初始都为1),每个房间至少有一个                dfs(l,j);                  if(cnt>bigest) bigest=cnt; //找到最大房间包括的方块数                ans++; // 房间数            }      printf("%d\n%d\n",ans,bigest);}  

拓展:

同学们知道为什么要写这些东西吗:

 if(!(map[l][j]&1)) q[l][j][0]=1;  if(!(map[l][j]&2)) q[l][j][1]=1;   if(!(map[l][j]&4)) q[l][j][2]=1;   if(!(map[l][j]&8)) q[l][j][3]=1;  

首先,取反(!)说明的是:1代表不行,0表示可以,在这里,同学们需要注意。那有些同学又有疑问了:为什么在check函数里判断的时候不加(!)?

bool check(int a,int b,int x) {   if(a<m&&b<n&&a>=0&&b>=0&&q[a][b][x]&&!flag[a][b]) return 1;  return 0;  }  

同学们可以仔细看一下check的运用:

  if(check(y+wayr[i],c+wayc[i],i))  

在这里我们可以知道,check是用来判断能不能走的,也就是用于计算在房间里有多少个方块的。能走得通,自然不能有墙
回归正题:为什么要写那些东西?
此关系到二进制。首先同学们要知道1、2、4、8用二进制怎么表示?二进制变化如下:

1->0001  2->0010  4->0100  8->1000【精英必知】120次方为1 ---> 即0001221次方为2 ---> 即0010322次方为4 ---> 即0100423次方为8 ---> 即1000......综上,第n个为:2的(n-1)次方。

通过上面,同学们可以观察到1、2、4、8转换为2进制后,可以很好的辨析出是否相等。

e.g:给你一个28,你能判断它有哪些墙了吗?首先28转换为2进制后为:11100可以对比一下:         00011001020100410008p.s:用一个数字表示方块周围的墙,1表示西墙,2表示北墙,4表示东墙,8表示南墙。同学们可以很清楚的看出28有:东墙、南墙。

所以同学们现在应该清楚了。

 if(!(map[l][j]&1)) q[l][j][0]=1;  if(!(map[l][j]&2)) q[l][j][1]=1;   if(!(map[l][j]&4)) q[l][j][2]=1;   if(!(map[l][j]&8)) q[l][j][3]=1;  

【意思】找是不是没有西墙、北墙、东墙、南墙。
p.s.同学们喜欢的话可以加关注,顶一个。Tanks!

原创粉丝点击