zoukankan      html  css  js  c++  java
  • luogu P1514 引水入城

    P1514 引水入城


    题目描述

    在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠。该国的行政区划十分特殊,刚好构成一个N 行M 列的矩形,如上图所示,其中每个格子都代表一座城市,每座城市都有一个海拔高度。

    为了使居民们都尽可能饮用到清澈的湖水,现在要在某些城市建造水利设施。水利设施有两种,分别为蓄水厂和输水站。蓄水厂的功能是利用水泵将湖泊中的水抽取到所在城市的蓄水池中。

    因此,只有与湖泊毗邻的第1 行的城市可以建造蓄水厂。而输水站的功能则是通过输水管线利用高度落差,将湖水从高处向低处输送。故一座城市能建造输水站的前提,是存在比它海拔更高且拥有公共边的相邻城市,已经建有水利设施。由于第N 行的城市靠近沙漠,是该国的干旱区,所以要求其中的每座城市都建有水利设施。那么,这个要求能否满足呢?如果能,请计算最少建造几个蓄水厂;如果不能,求干旱区中不可能建有水利设施的城市数目。


    输入输出格式

    输入格式:

    输入文件的每行中两个数之间用一个空格隔开。输入的第一行是两个正整数N 和M,表示矩形的规模。接下来N 行,每行M 个正整数,依次代表每座城市的海拔高度。

    输出格式:

    输出有两行。如果能满足要求,输出的第一行是整数1,第二行是一个整数,代表最少建造几个蓄水厂;如果不能满足要求,输出的第一行是整数0,第二行是一个整数,代表有几座干旱区中的城市不可能建有水利设施。


    输入输出样例

    输入样例#1:
    【输入样例1】
    2 5
    9 1 5 4 3
    8 7 6 1 2
    
    【输入样例2】
    3 6
    8 4 5 6 4 4
    7 3 4 3 3 3
    3 2 2 1 1 2
    输出样例#1:
    【输出样例1】
    1
    1
    
    【输出样例2】
    1
    3

    说明

    【样例1 说明】

    只需要在海拔为9 的那座城市中建造蓄水厂,即可满足要求。

    【样例2 说明】

    上图中,在3 个粗线框出的城市中建造蓄水厂,可以满足要求。以这3 个蓄水厂为源头

    在干旱区中建造的输水站分别用3 种颜色标出。当然,建造方法可能不唯一。

    【数据范围】


    对于每一个初始点进行一遍dfs搜索,路过每个点记录它能到的最左&右

    然后做一遍线段覆盖dp就OK了

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #define ll long long
    #include<queue>
    #define map hxhxhxffff033x3333ffff 
    using namespace std;
    const int maxn=1000;
    const int xx[5]={0,1,-1,0,0};
    const int yy[5]={0,0,0,1,-1};
    const int INT=1000;
    int read(){
        int an=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while('0'<=ch&&ch<='9'){an=an*10+ch-'0';ch=getchar();}
        return an*f;
    }
    int map[maxn][maxn],l[maxn][maxn],r[maxn][maxn],vis[maxn][maxn];
    int tot,n,m;
    void dfs(int x,int y){
        vis[x][y]=1;
        if(x==n){
            l[x][y]=r[x][y]=y;}
        else{
         l[x][y]=m+1;r[x][y]=0;}
        for(int i=1;i<=4;i++){
            int X=xx[i]+x,Y=yy[i]+y;
            if(X<=n)
            if(Y<=m)
            if(X>=1)
            if(Y>=1)
            if(map[X][Y]<map[x][y]){
            if(!vis[X][Y])dfs(X,Y);
            l[x][y] =min(l[x][y],l[X][Y]);
            r[x][y] =max(r[x][y],r[X][Y]);
            }
        }
    }
    struct saber{
    int l,r;
    }so[maxn];
    bool smp(saber x,saber y){
        if(x.l==y.l)return x.r>y.r;
        return x.l<y.l;
    }
    int main(){
        n=read();m=read();
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)map[i][j]=read();
        for(int i=1;i<=m;i++)dfs(1,i);
        for(int i=1;i<=m;i++)if(!vis[n][i])tot++;
        if(tot){
            cout<<"0
    "<<tot;return 0;}
        cout<<"1
    ";
        for(int i=1;i<=m;i++)
        so[i].l=l[1][i],so[i].r=r[1][i];
        sort(so+1,so+1+m,smp);
        int cur=2,i=1,ans=1;
        while(so[i].r<m){
            int p=i;
            while(cur<=m&&so[cur].l<=so[i].r+1){
                if(so[cur].r>so[p].r)p=cur;
                cur++;
            }
            i=p;
            ans++;
        }
        cout<<ans;
        return 0;
    }
    引水

    by:s_a_b_e_r


  • 相关阅读:
    HDU5000 (DP + 规律)
    HDU5127 神坑题---vector 、 list 、 deque 的用法区别
    HDU5128 细心、细心、细心
    dij单源最短路纯模板
    POJ 1236 SCC+缩点
    SCC(强连通分量)
    用树状数组求数组内的逆序对数
    HDU 1811 并查集
    大数模板,只要不是手敲,非常好用
    市赛
  • 原文地址:https://www.cnblogs.com/ck666/p/7532933.html
Copyright © 2011-2022 走看看