/* ID: m1590291 TASK: castle LANG: C++ */ #include <iostream> #include <string.h> #include <fstream> using namespace std; /****************************************************************************************************************** 是时候安利一波了,第一次做图论的题。用USACO上面的话说就是:Bigger Challenges 思路: 1, 直接将输入转化为一个图,找联通块,然后输出最大的。 2, 判断两个联通块之间是否相邻,若是,则将他们合并的方式和合并后的尺寸与当前最大值相比较, 3, 选取较大的,打印,完事。 代码思路: 1, 把每个格点都抽象为一个顶点,建图,然后进行连通分量的测试。 2, 直接用DFS更为简单,对每一个没有检查过的格点进行深搜, 3, 给每一个连通分量标记一个独立的标号(房间号),并记下每间房间的大小。 ******************************************************************************************************************/ int roomN=0; //房间数目 int room[55][55]; //每个空间所属房间号。(room[1][1] = 1 : 空间room[1][1] 属于编号为1的房间) int roomSize[51*51+1]; //每个房间的大小 int Msize=0; //最大房间大小 int wall[51][51][4]; //每个空间的墙壁状态。 值为1 表示有墙壁,0表示没墙壁。 //wall[i][j][0]:西 wall[i][j][1]:北 wall[i][j][2]:东 wall[i][j][3]:南 int f[51][51]; //检查是否涂灰 void dfs(int x,int y) { if(room[x][y] == roomN) return ; roomSize[roomN] ++; //大小++ f[x][y]=1; room[x][y]=roomN; //更新空间,找到所属房间编号 if(!wall[x][y][0]) dfs(x,y-1); //哪面没墙就 dfs if(!wall[x][y][1]) dfs(x-1,y); if(!wall[x][y][2]) dfs(x,y+1); if(!wall[x][y][3]) dfs(x+1,y); } int main() { ifstream fin("castle.in"); ofstream fout("castle.out"); int M,N; while(fin>>M>>N) { memset(wall,0,sizeof(wall)); memset(f,0,sizeof(f)); memset(room,0,sizeof(room)); memset(roomSize,0,sizeof(roomSize)); for(int i = 1;i <= N;i ++){ for(int j = 1;j <= M;j ++){ int temp; fin>>temp; for(int k = 0;k < 4;k ++) wall[i][j][k] = (temp>>k) & 1; //利用位运算得到墙壁状态 } } for(int i = 1;i <= N;i ++){ for(int j = 1;j <= M;j ++){ if(!f[i][j]){ roomN++; //房间数目,同时也是房间编号 dfs(i,j); Msize = (roomSize[roomN] > Msize) ? roomSize[roomN] : Msize; //一次dfs结束就找到了一个房间 //在图中相当于找得到了一个连通子图。因此更新Msize } } } fout<<roomN<<endl<<Msize<<endl; } /***************************************************************************************************************** 根据题意是 N 和 E,这两个方向优先考虑。因此遍历方向( 左下 -> 右上,先列后行) roomA : 当前房间编号 roomB : 当前房间上方空间的编号 (即北方 N) roomC : 当前房间右方空间的编号 (即东方 E) ans_x,ans_y : 空间坐标 di : 目标墙壁推动的方向 *****************************************************************************************************************/ Msize=0; int roomA,roomB,roomC; int ans_x,ans_y; char di; for(int i = 1;i <= M;i ++){ for(int j = N;j >= 1;j --){ roomA=room[j][i]; roomB=room[j-1][i]; roomC=room[j][i+1]; //概括讲就是。存在墙壁 && 相邻 && 不属于同一间房子 && 房间大小 > 当前最大大小. 然后更新相关数据即可 if(j > 1 && wall[j][i][1] && roomA != roomB && roomSize[roomA]+roomSize[roomB] > Msize){ Msize=roomSize[roomA]+roomSize[roomB]; ans_x=j; ans_y=i; di='N'; } else if(i < M && wall[j][i][2] && roomA != roomC && roomSize[roomA]+roomSize[roomC] > Msize){ Msize=roomSize[roomA]+roomSize[roomC]; ans_x=j; ans_y=i; di='E'; } } } fout<<Msize<<endl<<ans_x<<" "<<ans_y<<" "<<di<<endl; fin.close(); fout.close(); return 0; }