zoukankan      html  css  js  c++  java
  • codevs 1002 搭桥

    codevs 第一道题 

    先贴描述

    1002 搭桥

     

     时间限制: 1 s
     空间限制: 128000 KB
     题目等级 : 黄金 Gold
     
     
    题目描述 Description

    有一矩形区域的城市中建筑了若干建筑物,如果某两个单元格有一个点相联系,则它们属于同一座建筑物。现在想在这些建筑物之间搭建一些桥梁,其中桥梁只能沿着矩形的方格的边沿搭建,如下图城市1有5栋建筑物,可以搭建4座桥将建筑物联系起来。城市2有两座建筑物,但不能搭建桥梁将它们连接。城市3只有一座建筑物,城市4有3座建筑物,可以搭建一座桥梁联系两栋建筑物,但不能与第三座建筑物联系在一起。

    输入描述 Input Description

    在输入的数据中的第一行包含描述城市的两个整数r 和c, 分别代表从北到南、从东到西的城市大小(1 <= <= 50 and 1 <=  c <= 50). 接下来的r 行, 每一行由个(“#”)和(“.”)组成的字符. 每一个字符表示一个单元格。“#”表示建筑物,“.”表示空地。

    输出描述 Output Description

    在输出的数据中有两行,第一行表示建筑物的数目。第二行输出桥的数目和所有桥的总长度。

    样例输入 Sample Input

    样例1

    3 5

    #...#

    ..#..

    #...#

    样例2

    3 5

    ##...

    .....

    ....#

    样例3

    3 5

    #.###

    #.#.#

    ###.#

    样例4:

    3 5

    #.#..

    .....

    ....#

    样例输出 Sample Output

    样例1

    5

    4 4

    样例2

    2

    0 0

    样例3

    1

    0 0

    样例4

    3

    1 1

    数据范围及提示 Data Size & Hint

    见描述

      这题恶心的要死;

      做完整个人都是蒙比的;

      刚开始连思路都没有,还是看了题解才知道用搜索加最小生成树来做;

      然后我开始敲代码;

      第一遍敲完编译不通过,改了很久编译才通过;

      然后贴数据输出;

      结果连城市的数量都错;

      然后我就努力的调啊调;

      最后我发现,字符第一个元素是0,我tm却从1开始循环(这告我们脑子是个好东西);

      然后继续贴数据;

      第二个样例又不过了;

      好,继续改;

      然后,4向搜索问题一大堆。。(这告诉我们认真敲代码很重要);

      然后样例都过了;

      然后提交: 全wa,0分(我勒个擦!!);

      全wa后我开始思考为什么全wa;

      我发现可能是输入的问题;

      然后改输入,a了一个点;

      可能不是输入的问题;

      然后,我又把题目读了一边;

      如果某两个单元格有一个点相联系,则它们属于同一座建筑物。

      我日;

      我是按4向连接的;

      好吧改一下;

      改成八项;

      然后;

      ac了!;

      好吧,说一下思路:

      先把所有的数据读入;

      建立一个imap数组用来把读入的数据弄成数字;

      ‘.’是0;

      ‘#’是-1;

      然后循环全部,找到-1就开始广搜,把相连的-1变成不同楼房的标记;

      然后循环每一个标记,上下左右四个方向搜索;

      注意:

      因为是桥在边上,所以 要同时搜索相邻的两个格;

      然后,把搜到的边都记下来,跑一遍最小生成树就ac了;

      附代码:

      

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    int n,m,imap[51][51],ncon=0;
    char cmap[51][51];
    const int dx[9]={0,-1,-1,0,1,1,1,0,-1};
    const int dy[9]={0,0,1,1,1,0,-1,-1,-1};
    struct node {
        int name1,name2,dis;
    };
    struct node edge[100011];
    int fa[2501],num=0,ans=0;
    
    int find(int x)
    {
        if(fa[x]==x) return x;
        fa[x]=find(fa[x]);
        return fa[x];
    }
    
    void big(int x,int y,int dis)
    {
        imap[x][y]=dis;
        for(int i=1;i<=8;i++)
        {
            if(x+dx[i]>0&&x+dx[i]<=n&&y+dy[i]>0&&y+dy[i]<=m)
            {
                if(imap[x+dx[i]][y+dy[i]]==-1)
                {
                    big(x+dx[i],y+dy[i],dis);
                }
            }
        }
    }
    
    void edge_add(int from,int to,int dis)
    {
        num++;
        edge[num].name1=from;
        edge[num].name2=to;
        edge[num].dis=dis;
    }
    
    void edge_find_up(int x,int y,int from,int dis)
    {
        if(y-1>0&&x-1>0) if(imap[x-1][y-1]!=0&&imap[x-1][y-1]!=from) edge_add(from,imap[x-1][y-1],dis);
        if(y+1<=m&&x-1>0) if(imap[x-1][y+1]!=0&&imap[x-1][y+1]!=from) edge_add(from,imap[x-1][y+1],dis);
        if(x-1>0)
        {
            if(imap[x-1][y]!=0&&imap[x-1][y]!=from) edge_add(from,imap[x-1][y],dis);
            else if(imap[x-1][y]!=from) edge_find_up(x-1,y,from,dis+1);
        }
    }
    
    void edge_find_down(int x,int y,int from,int dis)
    {
        if(y-1>0&&x+1<=n) if(imap[x+1][y-1]!=0&&imap[x+1][y-1]!=from) edge_add(from,imap[x+1][y-1],dis);
        if(y+1<=m&&x+1<=n) if(imap[x+1][y+1]!=0&&imap[x+1][y+1]!=from) edge_add(from,imap[x+1][y+1],dis);
        if(x+1<=n)
        {
            if(imap[x+1][y]!=0&&imap[x+1][y]!=from)
            {
            //    printf("%d %d
    ",x+1,y);
                edge_add(from,imap[x+1][y],dis);
            }
            else if(imap[x+1][y]!=from) edge_find_down(x+1,y,from,dis+1);
        }
    }
    
    void edge_find_lift(int x,int y,int from,int dis)
    {
        if(x-1>0&&y-1>0) if(imap[x-1][y-1]!=0&&imap[x-1][y-1]!=from) edge_add(from,imap[x-1][y-1],dis);
        if(x+1<=n&&y-1>0) if(imap[x+1][y-1]!=0&&imap[x+1][y-1]!=from) edge_add(from,imap[x+1][y-1],dis);
        if(y-1>0)
        {
            if(imap[x][y-1]!=0&&imap[x][y-1]!=from) edge_add(from,imap[x][y-1],dis);
            else if(imap[x][y-1]!=from) edge_find_lift(x,y-1,from,dis+1);
        }
    }
    
    void edge_find_right(int x,int y,int from,int dis)
    {
        if(x-1>0&&y+1<=m) if(imap[x-1][y+1]!=0&&imap[x-1][y+1]!=from) edge_add(from,imap[x-1][y+1],dis);
        if(x+1<=n&&y+1<=m) if(imap[x+1][y+1]!=0&&imap[x+1][y+1]!=from) edge_add(from,imap[x+1][y+1],dis);
        if(y+1<=m)
        {
            if(imap[x][y+1]!=0&&imap[x][y+1]!=from) 
            {
            //    printf("%d %d
    ",x,y+1);
                edge_add(from,imap[x][y+1],dis);
            }
            else if(imap[x][y+1]!=from) edge_find_right(x,y+1,from,dis+1);
        }
    }
    
    void edge_build(int from,int x,int y)
    {
        if(x-1>0) edge_find_up(x-1,y,from,1);
        if(x+1<=n) edge_find_down(x+1,y,from,1);
        if(y-1>0) edge_find_lift(x,y-1,from,1);
        if(y+1<=m) edge_find_right(x,y+1,from,1);
    }
    
    int cmp(struct node a,struct node b)
    {
        return a.dis<b.dis;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            cin>>cmap[i]+1;
            for(int j=1;j<=m;j++)
            {
                if(cmap[i][j]=='#') imap[i][j]=-1;
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(imap[i][j]==-1)
                {
                    ncon++;
                    big(i,j,ncon);
                }
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(imap[i][j]!=0) edge_build(imap[i][j],i,j);
            }
        }
        sort(edge+1,edge+num+1,cmp);
        int head=0,zh=0,xx,yy;
        for(int i=1;i<=ncon;i++) fa[i]=i;
        while(head<=ncon&&zh<=num)
        {
            zh++;
            xx=find(edge[zh].name1),yy=find(edge[zh].name2);
            if(xx!=yy)
            {
                ans+=edge[zh].dis;
                fa[xx]=yy;
                head++;
            }
        }
        /*for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++) printf(" %d",imap[i][j]);
            printf("
    ");
        }*/
        printf("%d
    %d %d
    ",ncon,head,ans);
        return 0;
    }
  • 相关阅读:
    策略模式c++【转】
    [转]C++设计模式:Builder模式
    c/c++ 笔试面试题
    堆排序
    冒泡,快速,和堆排序
    C++继承
    【转】林建:计算机专业学习浅谈
    (centos)linux下访问双系统windows7文件系统
    sprintf() in c
    System call in linux by C
  • 原文地址:https://www.cnblogs.com/IUUUUUUUskyyy/p/5905602.html
Copyright © 2011-2022 走看看