题目大意:
给出一个城堡的平面图(考虑只有一层),城堡四周自然被墙包围,城堡中也有一些墙,这些墙与四周的墙构成了若干个房间。且如果推倒两个房间之间的墙,那么两个房间便会变成一个房间,那么易知会存在一堵墙(也可能不止一个)被推倒后会产生一个最大房间。
求城堡一共有几个房间,并且求推倒后能够产生最大房间的那堵墙。
下为城堡平面示意图:
1 2 3 4 5 6 7
#############################
1 # | # | # | | #
#####---#####---#---#####---#
2 # # | # # # # #
#---#####---#####---#####---#
3 # | | # # # # #
#---#########---#####---#---#
4 # -># | | | | # #
#############################
# =墙壁 -,| = 没有墙壁
-> =指向一面墙,这面墙推掉的话我们就有一间最大的新房间
这个城堡的平面图是7×4个单位的。一个“房间”的是平面图中一个由“#”、“-”、“|”围成的格子(就是图里面的那一个个的格子)。比如说这个样例就有5个房间。(大小分别为9、7、3、1、8个单位(排名不分先后))
移去箭头所指的那面墙,可以使2个房间合为一个新房间,且比移去其他墙所形成的房间都大。
城堡保证至少有2个房间,而且一定有一面墙可以被移走。
输入格式
第一行有两个整数:M和N 城堡的平面图用一个由数字组成的矩阵表示,一个数字表示一个单位,矩阵有N行M列。输入与样例的图一致。
每一个单位的数字告诉我们这个单位的东西南北是否有墙存在。每个数字是由以下四个整数的某个或某几个加起来的(四面都没有墙的话,这个数字应该为0)。
1: 在西面有墙 2: 在北面有墙
4: 在东面有墙 8: 在南面有墙
提示:城堡内部的墙会被规定两次。比如说(1,1)南面的墙,亦会被标记为(2,1)北面的墙。
输出格式
输出包含如下4行:
第 1 行: 城堡的房间数目。
第 2 行: 最大的房间的大小
第 3 行: 移除一面墙能得到的最大的房间的大小
第 4 行: 移除哪面墙可以得到面积最大的新房间。
选择最佳的墙来推倒。有多解时选最靠西的,仍然有多解时选最靠南的。同一格子北边的墙比东边的墙更优先。
用该墙的南邻单位的北墙或西邻单位的东墙来表示这面墙,方法是输出邻近单位的行数、列数和墙的方位("N"(北)或者"E"(东))。
样例输入
line 1: 7 4
line 2-N+1: 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
样例输出
line 1: 5
line 2: 9
line 3: 16
line 4: 4 1 E
题解
这道题我超时了很久,最后也没有想出什么好办法,主要是test里面的一组50X50的房间,每个房间只有一个单位大小。这个test在我程序里跑不出来,后来没办法,只能先取个巧,避过了这组test,然后通过了。。。。。。
题目要求的比较多,首先是由几个房间,这个比较简单,深搜就行了。在深搜的过程中,给每个房间标号,这样可以方便的知道每个房间的大小,第二问求最大房间大小就很简单了。
然后就是求推倒一座墙之后,可以构成一个最大的房间,我的做法是,把可能的最大房间大小从大到小排序,然后判断是否可以推倒某堵墙实现这个可能。这里也体现了之前给每个房间标号的作用。比较麻烦的是,可能有多堵墙可以实现最大房间,所以需要根据题目给出的优先顺序给出墙的位置。(其中很坑的是,当判断两房间是否可以组成最大房间的时候,由于涉及到一个为基准的问题,所以如果这两个房间可以组成最大房间,那么还要将这两个房间交换一下,再找一遍,依此找到最符合题目要求的墙,具体见程序)
代码
#include<stdio.h>
int N=0,M=0,m=0,room[51][51][5]={0};
int flag=0,cnt[25000]={0},g[4000000][3]={0};
int xy[2500][3]={0},p=0,flag1=0,flag2=0;
int v=0;
int count(int room[51][51][5])
{
int i,j;
for(i=0;i<M;i++)
for(j=0;j<N;j++)
cnt[room[i][j][4]]++;
return 0;
}
int mark(int room[51][51][5],int x,int y,int m)
{
if(x<0||y<0||x>=M||y>=N)
return 0;
if(room[x][y][4]==10000)
{
flag=1;
room[x][y][4]=m;
if(room[x][y][0]==0)
mark(room,x,y-1,m);
if(room[x][y][1]==0)
mark(room,x-1,y,m);
if(room[x][y][2]==0)
mark(room,x,y+1,m);
if(room[x][y][3]==0)
mark(room,x+1,y,m);
}
return 0;
}
int fid(int room[51][51][5],int a,int b)
{
int i,j;
for(j=0;j<N;j++)
for(i=M-1;i>=0;i--)
{
if(room[i][j][4]==a)
{
if(room[i][j][0]==1)
{
flag2=0;
if(i<0||j<1||i>=M||j>=N+1)
flag2=1;
if(room[i][j-1][4]==b&&flag2==0)
{
flag1=1;
xy[p][0]=i;
xy[p][1]=j;
xy[p][2]=1;
p++;
}
}
if(room[i][j][1]==1)
{
flag2=0;
if(i<1||j<0||i>=M+1||j>=N)
flag2=1;
if(room[i-1][j][4]==b&&flag2==0)
{
flag1=1;
xy[p][0]=i;
xy[p][1]=j;
xy[p][2]=2;
p++;
}
}
if(room[i][j][2]==1)
{
flag2=0;
if(i<0||j<-1||i>=M||j>=N-1)
flag2=1;
if(room[i][j+1][4]==b&&flag2==0)
{
flag1=1;
xy[p][0]=i;
xy[p][1]=j;
xy[p][2]=3;
p++;
}
}
if(room[i][j][3]==1)
{
flag2=0;
if(i<-1||j<0||i>=M-1||j>=N)
flag2=1;
if(room[i+1][j][4]==b&&flag2==0)
{
flag1=1;
xy[p][0]=i;
xy[p][1]=j;
xy[p][2]=4;
p++;
}
}
}
}
return 0;
}
int main()
{
int xy1,xy2,xy3;
int sum,max,mmax;
long int i,j;
long int k=0,t;
m=1;
scanf("%d %d",&N,&M);
for(i=0;i<M;i++)
for(j=0;j<N;j++)
{
scanf("%ld",&t);
room[i][j][0]=t%2;
t=t/2;
room[i][j][1]=t%2;
t=t/2;
room[i][j][2]=t%2;
t=t/2;
room[i][j][3]=t%2;
room[i][j][4]=10000;
}
for(j=0;j<N;j++)
for(i=M-1;i>=0;i--)
{
flag=0;
mark(room,i,j,m);
if(flag==1)
m++;
}
count(room);
sum=m-1;
max=cnt[1];
for(i=1;i<m;i++)
{
if(max<cnt[i])
max=cnt[i];
}
k=0;
for(t=2500-sum+2;t>0;t--)
for(i=1;i<m;i++)
for(j=i+1;j<m;j++)
{
if(t==cnt[i]+cnt[j]&&k<40000)
{g[k][0]=t;
g[k][1]=i;
g[k][2]=j;
k++;}
}
for(i=0;i<k;i++)
{
flag1=0;
fid(room,g[i][1],g[i][2]);
if(flag1==1)
{mmax=g[i][0];break;}
}
xy1=xy[0][0];xy2=xy[0][1];xy3=xy[0][2];
p=0;
fid(room,g[i][2],g[i][1]);
if(xy2<xy[0][1])
{
xy[0][0]=xy1;
xy[0][1]=xy2;
xy[0][2]=xy3;
}
if(xy2==xy[0][1]&&xy1>xy[0][0])
{
xy[0][0]=xy1;
xy[0][1]=xy2;
xy[0][2]=xy3;
}
printf("%d\n%d\n%d\n%d %d ",sum,max,mmax,xy[0][0]+1,xy[0][1]+1);
if(xy[0][2]==1)
printf("%c\n",'W');
if(xy[0][2]==2)
printf("%c\n",'N');
if(xy[0][2]==3)
printf("%c\n",'E');
if(xy[0][2]==4)
printf("%c\n",'S');
return 0;
}