/*
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;
}
USACO 2.1-The Castle
最新推荐文章于 2021-03-17 01:19:29 发布