USACO 2.1-The Castle

来源:互联网 发布:win10 软件兼容 编辑:程序博客网 时间:2024/05/16 17:53
/*ID: m1590291TASK: castleLANG: 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;}

0 0
原创粉丝点击