zoukankan      html  css  js  c++  java
  • 洪水 Pow

    Description

    AKD市处在一个四面环山的谷地里。最近一场大暴雨引发了洪水,AKD市全被水淹没了。Blue Mary,AKD市的市长,召集了他的所有顾问(包括你)参加一个紧急会议。经过细致的商议之后,会议决定,调集若干巨型抽水机,将它们放在某些被水淹的区域,而后抽干洪水。 
    你手头有一张AKD市的地图。这张地图是边长为m*n的矩形,被划分为m*n个1*1的小正方形。对于每个小正方形,地图上已经标注了它的海拔高度以及它是否是AKD市的一个组成部分。地图上的所有部分都被水淹没了。并且,由于这张地图描绘的地面周围都被高山所环绕,洪水不可能自动向外排出。显然,我们没有必要抽干那些非AKD市的区域。 
    每个巨型抽水机可以被放在任何一个1*1正方形上。这些巨型抽水机将持续地抽水直到这个正方形区域里的水被彻底抽干为止。当然,由连通器原理,所有能向这个格子溢水的格子要么被抽干,要么水位被降低。每个格子能够向相邻的格子溢水,“相邻的”是指(在同一高度水平面上的射影)有公共边。 

    Input

    第一行是两个数m,n(1<=m,n<=1000). 
    以下m行,每行n个数,其绝对值表示相应格子的海拔高度;若该数为正,表示他是AKD市的一个区域;否则就不是。 
    请大家注意:所有格子的海拔高度其绝对值不超过1000,且可以为零. 

    Output

    只有一行,包含一个整数,表示至少需要放置的巨型抽水机数目。 

     

    Sample Input

    6 9
    -2 -2 -1 -1 -2 -2 -2 -12 -3
    -2 1 -1 2 -8 -12 2 -12 -12
    -5 3 1 1 -12 4 -6 2 -2
    -5 -2 -2 2 -12 -3 4 -3 -1
    -5 -6 -2 2 -12 5 6 2 -1
    -4 -8 -8 -10 -12 -8 -6 -6 -4
     
     

    Sample Output

    2

    Hint


    题解:

    结论:若在I放置一个抽水机,且J与I之间存在一条路径使得max(H)<=H[j],那么J的水可以被抽干。所以显然我们要在所有“山谷”放抽水机。

    将格子按高度从小到大加入,加入I时将其与相邻的格子并入一个集合,若I需要抽水且合并后I属于的集合没有抽水机则在I处放置一个抽水机。

    细节:将同一高度的格子合并完后再放置抽水机。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<cstdlib>
    using namespace std;
    int n,m,tot,ans,last=1;
    int map[1000005],h[1000005],b[1000005],vis[1000005],t[5]={-1,0,1,0,-1},p[1000005],father[1000005];
    int gi()
    {
        int ans=0,f=1;
        char i=getchar();
        while(i<'0'||i>'9'){if(i=='-')f=-1;i=getchar();}
        while(i>='0'&&i<='9'){ans=ans*10+i-'0';i=getchar();}
        return ans*f;
    }
    int make(int x,int y)
    {
        return (x-1)*m+y;
    }
    bool cmp(int a,int b)
    {
        return h[a]<h[b];
    }
    int find(int x)
    {
        if(father[x]==x)return x;
        else return father[x]=find(father[x]);
    }
    int main()
    {
        int i,j;
        n=gi();m=gi();
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            {
                int x=make(i,j);
                h[x]=gi();
                father[x]=x;
                map[++tot]=x;
                if(h[x]>0)b[x]=1;
                else h[x]=-h[x];
            }
        }
        sort(map+1,map+tot+1,cmp);
        for(i=1;i<=tot;i++)
        {
            int a=map[i],y=(a-1)%m+1,x=(a-1)/m+1;
            for(j=0;j<4;j++)
            {
                int xx=x+t[j],yy=y+t[j+1];
                if(xx>=1&&xx<=n&&yy>=1&&yy<=m)
                {
                    int b=make(xx,yy);
                    if(vis[b])
                    {
                        int fa=find(b);
                        p[a]|=p[fa];
                        father[fa]=find(a);
                    }
                }
            }
            vis[a]=1;
            if(h[map[i]]!=h[map[i+1]])
            {
                for(j=last;j<=i;j++)
                {
                    if(b[map[j]]&&!p[find(map[j])])
                    {
                        ans++;
                        p[find(map[j])]=1;
                    }
                }
                last=i+1;
            }
        }
        printf("%d
    ",ans);
        return 0;
    }

    转载于:https://www.cnblogs.com/huangdalaofighting/p/7219579.html

  • 相关阅读:
    白盒测试方法
    单元测试 集成测试 系统测试
    快慢指针原理和应用
    实例方法,类方法,静态方法区别
    查找算法
    排序算法整理
    Oracle sql developer 删表时遇到问题unique/primary keys in table referenced by foreign keys
    剑指 Offer 18. 删除链表的节点(简单)
    剑指 Offer 17. 打印从1到最大的n位数(简单)
    Cyberdebut的补题列表
  • 原文地址:https://www.cnblogs.com/twodog/p/12139869.html
Copyright © 2011-2022 走看看