参考思路:http://blog.csdn.net/dragonfly_xp/article/details/5504031
http://blog.tianya.cn/blogger/post_show.asp?BlogID=1144082&PostID=10566902
学习了FloodFill方法以及位运算 if((wall[row][col] & 1) == 0) FloodFill(row, col - 1, color);
注意题目里说了:choose 'N' before 'E'。 所以最后在遍历墙,合并房间的时候,注意顺序,从最西南角,先向N遍历每一列,然后向E遍历。即外层循环遍历column,内层循环遍历row。
算法分析:
这是一道比较综合的题目,我觉得关键就是在于如何处理好给的数据。
开始一看,觉得用这样的方式描述一个矩阵还不大习惯。可仔细一看,发现四个方向分别用
1、2、4、8表示,这就让我想起了二进制。再把样例加以分析,拿11来说,把它化成二进制为1011,从第一位到第四位分别对应北东南西,然后在存储下来,这样就把给的信息转化成能直接运用的了!
再来看,它的几个任务。
1、求房间数
一开始就觉得跟迷宫类似。便选择了用BFS。
从(1,1)开始对每个未染色的房间染色。每次到此块全部染色完,就累加ROOM。
进行多次BFS,直到全部房间都染色,便得出第一问结果。
2、求最大房间大小
因为已经给不同房间染了不同色,这样就能很方便的找出最大房间大小。
3、移除一面墙能得到的最大的房间的大小
这里,我选择了用枚举每个墙来找最优解。
因为在之前先记录下了每个房间的大小,所以只需要判断移除的墙两侧不为同一房间,且比最优值更优,就可以更新。
我的代码
/*
ID: wangxin12
PROG: castle
LANG: C++
*/
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;
#define MAX 51
int wall[MAX][MAX];
int M,N; // M cols, N rows
int i, j; //计数用
int visited[MAX][MAX];
int roomnum;
vector<int> roomsize;
int bigroom;
void FloodFill(int row, int col, int color);
int vergeSize;
int vergeRow;
int vergeCol;
char vergeDirection;
int main() {
//input
ifstream fin("castle.in");
ofstream fout("castle.out");
fin>>M>>N;
for(i = 0; i < N; i++) {
for(j = 0; j < M; j++) {
int temp;
fin>>temp;
wall[i][j] = temp;
}
}
fin.close();
//floodfill 求房间数目
for(i = 0; i < N; i++) {
for(j = 0; j < M; j++) {
if(visited[i][j] == 0) FloodFill(i, j, ++roomnum);
}
}
fout<<roomnum<<endl;
//求最大的房间大小
for(i = 0; i < roomnum; i++) roomsize.push_back(0);
for(i = 0; i < N; i++) {
for(j = 0; j < M; j++) {
int temp = visited[i][j];
roomsize[temp - 1]++;
}
}
for(i = 0; i < roomnum; i++) {
if(bigroom < roomsize[i]) bigroom = roomsize[i];
}
fout<<bigroom<<endl;
//求合并后最大的房间
for(j = 0; j < M; j++) {
for(i = N - 1; i >= 0; i--) {
//和North的墙
if( i - 1 >= 0 && visited[i][j] != visited[i - 1][j]) {
int first = visited[i][j];
int second = visited[i - 1][j];
int total = roomsize[first - 1] + roomsize[second - 1];
if(vergeSize < total) {
vergeSize = total;
vergeRow = i + 1;
vergeCol = j + 1;
vergeDirection = 'N';
}
}
//和East的墙
if( j + 1 < M && visited[i][j] != visited[i][j + 1]) {
int first = visited[i][j];
int second = visited[i][j + 1];
int total = roomsize[first - 1] + roomsize[second - 1];
if(vergeSize < total) {
vergeSize = total;
vergeRow = i + 1;
vergeCol = j + 1;
vergeDirection = 'E';
}
}
}
}
fout<<vergeSize<<endl;
fout<<vergeRow<<" "<<vergeCol<<" "<<vergeDirection<<endl;
//Output
//ofstream fout("out.txt");
fout.close();
return 0;
}
void FloodFill(int row, int col, int color) {
if(row < 0 || col < 0 || row >= 50 || col >= 50) return;
if(visited[row][col] != 0) return;
visited[row][col] = color;
if((wall[row][col] & 1) == 0) FloodFill(row, col - 1, color);
if((wall[row][col] & 2) == 0) FloodFill(row - 1, col, color);
if((wall[row][col] & 4) == 0) FloodFill(row, col + 1, color);
if((wall[row][col] & 8) == 0) FloodFill(row + 1, col, color);
return;
}