城堡问题

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 ---> 即0001
221次方为2 ---> 即0010
322次方为4 ---> 即0100
423次方为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!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值