题解:
这道题真的好蛋疼啊,首先题意不好理解,搞了半天复杂的要死,有那么多要求,还要求那么多东西,做到一半都不想做了。。。感觉没什么技术含量,还做起来死费劲儿。但是强迫症非得按顺序做题啊,最后还是一点点把它给调出来了,说什么flood fill,其实也就是那么回事,没什么算法上的技巧,就是见招拆招的感觉。。。
题意搞懂再做题,题意,不谢!
第一步:根据他的规则把房间画出来,遍历一遍把每个节点四面的墙给补上;
第二步:深搜;
目的1:记录深搜的次数,房间数;
目的2:记录深搜的深度,最大房间面积;
目的3:把属于同一棵树的节点标记起来,也就是染色的过程,为下一步打通房间铺路;
注意:在深搜的过程中搜的深度要注意如何保存,会有分叉以及分叉后再汇合的情况出现,我是设置了一个全局变量deep来记录深度;
第三步:打墙;
题目说了,只能打一次,而且还有规则,先紧着西边的选,如果同样靠西要先紧着南边的选,所以要注意遍历的方向。打墙的时候就凸显之前标色的重要性了,首先得找到墙,然后墙两边的颜色还要不一样,从下往上,从左往右遍历一遍找到最优解。
PS:注意数组大小。
代码实现:
/*
ID: eashion
LANG:C++
TASK:castle
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define MAX 55
using namespace std;
int N,M;
int Sum;
int Size;
int deep;
int BSize;
int bx,by;
int color;
int Csize[MAX*MAX];
char oritation;
int maze[MAX][MAX];
int dx[4] = {1,0,-1,0};
int dy[4] = {0,-1,0,1};
int castle[MAX*3][MAX*3];
void solve();
void dfs(int x,int y,int col);
void Break();
int main()
{
freopen("castle.in","r",stdin);
freopen("castle.out","w",stdout);
scanf("%d%d",&M,&N);
for( int i = 1; i <=N; i++ ){
for( int j = 1; j <= M; j++ ){
scanf("%d",&maze[i][j]);
}
}
solve();
return 0;
}
void solve(){
Sum = 0;
Size = 0;
BSize = 0;
color = 2;
memset(Csize,0,sizeof(Csize));
memset(castle,0,sizeof(castle));
//补墙,用到了&运算
for( int i = 1; i <= N; i++ ){
for( int j = 1; j <= M; j++ ){
int tx = i*2-1;
int ty = j*2-1;
if( (maze[i][j]&1) == 1 ){
castle[tx][ty-1] = 1;
}
if( (maze[i][j]&2) == 2 ){
castle[tx-1][ty] = 1;
}
if( (maze[i][j]&4) == 4 ){
castle[tx][ty+1] = 1;
}
if( (maze[i][j]&8) == 8 ){
castle[tx+1][ty] = 1;
}
}
}
//补四面的墙
for( int i = 0; i <= 2*N; i++ ){
castle[i][0] = 1;
}
for( int i = 0; i <= 2*N; i++ ){
castle[i][2*M] = 1;
}
for( int i = 0; i <= 2*M; i++ ){
castle[0][i] = 1;
}
for( int i = 0; i <= 2*M; i++ ){
castle[2*N][i] = 1;
}
//补节点处的墙,其实也不太会访问到
for( int i = 2; i <= 2*N; i+=2 ){
for( int j = 2; j <= 2*M; j+=2 ){
castle[i][j] = 1;
}
}
// for( int i = 0; i <= 2*N; i++ ){
// for( int j = 0; j <= 2*M; j++ ){
// printf("%d",castle[i][j]);
// }
// printf("\n");
// }
//深搜
for( int i = 1; i <= N; i++ ){
for( int j = 1; j <= M; j++ ){
int tx = i*2-1;
int ty = j*2-1;
deep = 0;
if( castle[tx][ty] == 0 ){
dfs(tx,ty,color++);
Csize[color-1] = deep;
Sum++;
Size = max(Size,deep);
}
}
}
//打墙
Break();
printf("%d\n",Sum);
printf("%d\n",Size);
printf("%d\n",BSize);
printf("%d %d %c\n",bx,by,oritation);
}
void dfs(int x,int y,int col){
//每进入一次深度+1
deep++;
//标色
castle[x][y] = col;
for( int i = 0; i < 4; i++ ){
int nx = x+dx[i];
int ny = y+dy[i];
int nnx = nx+dx[i];
int nny = ny+dy[i];
//必须保证两个同时为0,因为下个节点可能会已经被染色,导致重复染色
if( castle[nx][ny] == 0 && castle[nnx][nny] == 0 ){
castle[nx][ny] = col;
dfs(nnx,nny,col);
}
}
return ;
}
void Break(){
//注意遍历顺序
for( int j = 0; j <= 2*M; j++ ){
for( int i = 2*N; i >= 0; i-- ){
if( castle[i][j] == 1 ){
int ux,uy;
int dx,dy;
int rx,ry;
int lx,ly;
ux = i-1,uy = j;
dx = i+1,dy = j;
rx = i,ry = j+1;
lx = i,ly = j-1;
//上下打通
if( ux >= 0 && dx <= 2*N && castle[ux][uy]!=castle[dx][dy] ){
int tmp = Csize[castle[ux][uy]]+Csize[castle[dx][dy]];
if( BSize < tmp ){
BSize = tmp;
bx = (dx+1)/2;
by = (dy+1)/2;
oritation = 'N';
}
}
//左右打通
if( ly >= 0 && ry <= 2*M && castle[lx][ly]!=castle[rx][ry] ){
int tmp = Csize[castle[lx][ly]]+Csize[castle[rx][ry]];
if( BSize < tmp ){
BSize = tmp;
bx = (lx+1)/2;
by = (ly+1)/2;
oritation = 'E';
}
}
//把上下放前面,而且严格BSize < tmp,保证了若有可能先打‘N’
}
}
}
}