这是道floodfill题,用DFS对每个square扩展很容易得到room的个数以及面积大小。square扩展时用到位运算,每次扩展到下一个square,应将扩展的入口堵住,避免重复扩展甚至死循环。然后枚举打开每一堵墙(最外围的墙除外),当墙两边不属于同一个房间且面积之和最大时即得解。为了避免排序,应从西向东,从南向北的顺序枚举。
/*
ID: xpli1
PROG: castle
LANG: C++
*/
#include <iostream>
#include <fstream>
#include <cstdio>
#include <cmath>
using namespace std;
#define OUT cout
#define IN cin
#define MAXNUM 51*51
ofstream fout ("castle.out");
ifstream fin ("castle.in");
int wall[MAXNUM];
int sq_rm[MAXNUM];
int sq_num[MAXNUM];
int M,N;
int roomnum;
int max_sq_num = -1;
int max_sq_num_move = -1;
int ii,jj;
char direction;
void dfs(int k,int dir){
if(sq_rm[k]) return;
sq_rm[k] = roomnum;
sq_num[roomnum]++;
int WALL = wall[k]+dir; // 将入口堵住
if(!(WALL & 1)) dfs(k-1,4);
if(!(WALL & 2)) dfs(k-M,8);
if(!(WALL & 4)) dfs(k+1,1);
if(!(WALL & 8)) dfs(k+M,2);
}
void mkbigest(){
int i,j;
for(i=0; i<N; i++){
wall[i*M + 0] -= 1;
wall[i*M + M-1] -= 4;
}
for(i=0; i<M; i++){
wall[i] -= 2;
wall[(N-1)*M+i] -= 8;
}
int index,rmnum;
for(j=0; j<M; j++){
for(i=N-1; i>=0; i--){
index = i*M+j;
if(wall[index]&2 && sq_rm[index] != sq_rm[index-M]){
rmnum = sq_num[sq_rm[index]]+sq_num[sq_rm[index-M]];
if(max_sq_num_move < rmnum){
max_sq_num_move = rmnum;
ii = i+1;
jj = j+1;
direction = 'N';
}
}
}
for(i=N-1; i>=0; i--){
index = i*M+j;
if(wall[index]&4 && sq_rm[index] != sq_rm[index+1]){
rmnum = sq_num[sq_rm[index]]+sq_num[sq_rm[index+1]];
if(max_sq_num_move < rmnum){
max_sq_num_move = rmnum;
ii = i+1;
jj = j+1;
direction = 'E';
}
}
}
}
}
int main()
{
IN >> M >> N;
int i;
for(i=0; i<M*N; i++)
IN >> wall[i];
for(i=0; i<M*N; i++){
if(sq_rm[i]) continue;
roomnum++;
dfs(i,0);
}
OUT<< roomnum << endl;
for(i=0; i<roomnum+1; i++){
if(max_sq_num < sq_num[i])
max_sq_num = sq_num[i];
}
OUT << max_sq_num << endl;
mkbigest();
OUT << max_sq_num_move << endl;
OUT << ii << ' ' << jj << ' '<< direction << endl;
return 0;
}