1250:The Castle
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 5332 通过数: 2746
【题目描述】
一座城堡被分成m*n个方块(m≤50,n≤50),每个方块可有0~4堵墙(0表示无墙)。下面示出了建筑平面图:
图中的加粗黑线代表墙。几个连通的方块组成房间,房间与房间之间一定是用黑线(墙)隔开的。
现在要求你编一个程序,解决以下2个问题:
1、该城堡中有多少个房间?
2、最大的房间有多大?
【输入】
平面图用一个数字表示一个方块(第1个房间用二进制1011表示,0表示无东墙,用十进制11表示)。
第一行一个整数m(m≤50),表示房子南北方向的长度。
第二行一个整数n(n≤50),表示房子东西方向的长度。
后面的m行,每行有n个整数,每个整数都表示平面图对应位置的方块的特征。每个方块中墙的特征由数字P来描述(0≤P≤15)。数字P是下面的可能取的数字之和:
1(西墙 west)
2(北墙 north)
4(东墙 east)
8(南墙 south)
室内的墙被定义两次: 例如方块(1,1)中的南墙也被位于其南面的方块(2,1)定义了一次。
建筑中至少有两个房间。
【输出】
第1行:一个整数,表示房间总数;
第2行:一个整数,表示最大房间的面积(方块数)。
【输入样例】
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】
C代码如下:
#include<stdio.h>
int map[51][51][4];
int d,m,n,i,j;
int num=0,maxmj; //num为房间数,maxmj为房间最大面积
int dx[4]={0,1,0,-1}; // 方向数组
int dy[4]={1,0,-1,0};
int fj[51][51]={0}; //fj[x][y],(x,y)坐标所在的房间号
//map[i][j][0]记录第i行第j列的房间南边是否有墙,=1,有墙,=0无墙
//map[i][j][1]记录第i行第j列的房间东边是否有墙,=1,有墙,=0无墙
//map[i][j][2]记录第i行第j列的房间北边是否有墙,=1,有墙,=0无墙
//map[i][j][3]记录第i行第j列的房间西边是否有墙,=1,有墙,=0无墙
int que[2501][3]; //que为队列,q[i][0]为队列中第i个房间的横坐标,q[i][1]为纵坐标
void bfs(int p,int q) //从第p行第q列的房间开始广搜
{
int t;
int p1=p,q1=q;
int fjmj=1; //房间的面积
int head=0,tail=1,x1,y1,x,y;
num++; //找到的房间数加1
fj[p1][q1]=num; //贴上房间号
que[1][0]=p1;
que[1][1]=q1;
while(head<tail)
{
head++;
for(t=0;t<=3;t++)//右、下、左、上四个方向搜索
{
x1=que[head][0];
y1=que[head][1];
x=x1+dx[t];
y=y1+dy[t];
if(1<=x && x<=m && 1<=y && y<=n && (fj[x][y]==0))//未超出边界
{
//t=0,1,2,3,分别向右、向下,向左、向上搜索
if(map[x][y][3-t]==0 && map[x1][y1][(5-t)%4]==map[x][y][3-t])
{
//入队
tail++;
fj[x][y]=num;//贴上房间号
fjmj++;
que[tail][0]=x;
que[tail][1]=y;
}
}
}
}
if(maxmj<fjmj)
maxmj=fjmj;
return;
}
int main()
{
scanf("%d%d",&m,&n);//m行n列
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
{
scanf("%d",&d);
if(d==15) //d=15,这个小房间四面都是墙
{
num++; //生成新的房间号
if(maxmj<1)
maxmj=1;
fj[i][j]=num;//贴上新房间号
}
int t=3;
while(d>0)//将输入的数字转为二进制,并保存在数组中
{
map[i][j][t]=d%2;
d=d/2;
t--;
}
}
for(i=1;i<=m;i++)
{
for(j=1;j<=n;j++)
{
if(fj[i][j]==0)//房间号为0,第i行第j列不属于一个房间
bfs(i,j);
}
}
printf("%d\n%d\n",num,maxmj);
return 0;
}
【参考代码2】
C++代码如下:
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
struct node
{
int x;
int y;
};
int n,m; //地图尺寸
int mp[255][255][6]; //地图数组,mp[i][j][0]记录是第几个房间,mp[i][j][1..4]记录该方向是否有障碍
int dir[5][2]={{0},{0,-1},{-1,0},{0,1},{1,0}}; //方向数组
int a[5]={0,1,2,4,8}; //障碍数组
int ans; //房间数目
void bfs(int x,int y,int t)
{
queue <node>q;
node s,tmp;
s.x=x;
s.y=y;
q.push(s);
ans++;
mp[x][y][0]=t;
while(!q.empty())
{
node nw=q.front();
for(int i=1;i<=4;i++)
{
int x1=nw.x+dir[i][0];
int y1=nw.y+dir[i][1];
tmp.x=x1;
tmp.y=y1;
if(x1>0 && x1<=m && y1>0 && y1<=n && !mp[nw.x][nw.y][i] && !mp[x1][y1][0])
{
mp[x1][y1][0]=t;
q.push(tmp);
ans++;
}
}
q.pop();
}
}
int main()
{
cin>>m>>n;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
int p;
cin>>p;
for(int k=4;k>0;k--)
{
if(p-a[k]>=0)
{
p-=a[k];
mp[i][j][k]=1;
}
}
}
}
int t=1; //房间总数
int maxn=0; //最大房间数
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
if(!mp[i][j][0])
{
bfs(i,j,t++);
maxn=max(maxn,ans);
ans=0;
}
}
}
cout<<t-1<<endl<<maxn<<endl;
}