zoukankan      html  css  js  c++  java
  • USACO 2.1-The Castle

    /*
    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;
    }
    


  • 相关阅读:
    【纪中集训2019.3.19】原样输出
    【纪中集训2019.3.11】树上四次求和
    【纪中集训2019.3.11】Cubelia
    【纪中集训2019.3.14】小凯的疑惑
    leetcode 18 4Sum
    leetcode 17 Letter Combinations of a Phone Number
    leetcode 11 Container With Most Water
    leetcode 16 3Sum Closest
    leetcode 15 3Sum
    leetcode 14 Longest Common Prefix
  • 原文地址:https://www.cnblogs.com/Jstyle-continue/p/6352026.html
Copyright © 2011-2022 走看看