• P1514 引水入城 DFS


      

    题目描述

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

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

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

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

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


    非常好的一道搜索题目
    贪心+DFS即可解决 这题DFS很简单 主要是后期处理

    #include<bits/stdc++.h>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);--i)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m)
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define ll long long
    #define REP(i,N)  for(int i=0;i<(N);i++)
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    #define inf 0x3f3f3f3f
    #define N 5005
    int n,m;
    int mp[N][N];
    int vis[N][N];
    int vis2[N];
    int ri[N];
    vector<int>node[N];//该城市所到达的点
    vector<int>in[N];//到达该点的城市
    bool inmap(int x,int y)
    {
        return x>=1&&x<=n&&y>=1&&y<=m;
    }
    int dx[]={0,0,1,-1};
    int dy[]={1,-1,0,0};
    void dfs(int x,int y,int flag)
    {
        if(x==n)
        {
            node[flag].push_back(y);
            ri[flag]=max(ri[flag],y);
            in[y].push_back(flag);
            vis2[y]=1;
        }
        rep(i,0,3)
        {
            int a=x+dx[i];
            int b=y+dy[i];
            if(!inmap(a,b))continue;
            if(vis[a][b]==flag)continue;
            if(mp[a][b]>=mp[x][y])continue;
            vis[a][b]=flag;
            dfs(a,b,flag);
        }
    }
    struct aaa
    {
        int id,h;
    }s[N];
    bool cmp(aaa a,aaa b)
    {
        return a.h>b.h;
    }
    int main()
    {
        RII(n,m);
        rep(i,1,n)
        rep(j,1,m)
        {
            RI(mp[i][j]);
            if(i==1)
            s[j].id=j,s[j].h=mp[i][j];
        }
        sort(s+1,s+1+m,cmp);//贪心优化 高的先来  剪了30ms。。。
    
        rep(i,1,m)
        if(!vis[1][ s[i].id ])
        dfs(1,s[i].id,s[i].id);
        
        int ok=1;
        int cnt=0;
        rep(i,1,m)
        if(!vis2[i])ok=0,cnt++;
        if(!ok)printf("%d
    %d",0,cnt);
        else
        {
            printf("1
    ");
            
            int sum=0;
            int i=1;
            while(i<=m)
            {
                int maxx=0;
                rep(j,0,in[i].size()-1)
                    maxx=max(maxx, ri[ in[i][j] ] );
                
                sum++;
                i=maxx+1;
            }
            cout<<sum;
        }
        return 0;
    }
    View Code
    大佬的做法   速度比我的快一倍QAQ

    递归求左界和右界非常巧妙
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #include <vector>
    #include <queue>
    #include <algorithm>
    #include <stack>
    using namespace std;
    #define maxn 510
    #define nx x+xx[i]
    #define ny y+yy[i]
    int l[maxn][maxn],r[maxn][maxn];
    int high[maxn][maxn];
    int n,m;
    bool vis[maxn][maxn];
    int xx[4]={-1,0,1,0};
    int yy[4]={0,1,0,-1};
    int qx[maxn*maxn],qy[maxn*maxn];
    
    inline void dfs(int x,int y)
    {
        vis[x][y]=true;
        for (int i=0;i<4;i++){
            if (nx<1 || nx>n || ny<1 || ny>m) continue;
            if (high[nx][ny]>=high[x][y]) continue;
            if (!vis[nx][ny])dfs(nx,ny);
            l[x][y]=min(l[x][y],l[nx][ny]);
            r[x][y]=max(r[x][y],r[nx][ny]);
        }
    }
    
    inline int read()
    {
        int ret=0;
        char c=getchar();
        while (c<'0' || c>'9') c=getchar();
        while (c>='0' && c<='9'){
            ret=ret*10+c-'0';
            c=getchar();
        }
        return ret;
    }
    
    int main()
    {
        n=read();
        m=read();
        memset(vis,false,sizeof(vis));
        memset(l,0x3f,sizeof(l));
        memset(r,0,sizeof(r));
        for (int i=1;i<=m;i++)
            l[n][i]=r[n][i]=i;
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++)    
                high[i][j]=read();
        for (int i=1;i<=m;i++)
            if (!vis[1][i]) dfs(1,i);
        bool flag=false;
        int cnt=0;
        for (int i=1;i<=m;i++)    
            if (!vis[n][i]){
                flag=true;
                cnt++;
            }
        if (flag){
            puts("0");
            printf("%d",cnt);
            return 0;
        }
        int left=1;
        while (left<=m){
            int maxr=0;
            for (int i=1;i<=m;i++)
                if (l[1][i]<=left)
                    maxr=max(maxr,r[1][i]);
            cnt++;
            left=maxr+1;
        }
        puts("1");
        printf("%d",cnt);
    }
    View Code






  • 相关阅读:
    在Java中,final修饰的类有什么特点
    基于 枚举值 输出 枚举描述的 jackson 自定义注解方法
    基于 r2dbc jpa java reactor流式编程的查询合并
    分组后 排除存在某种情况的 的查询
    基于Mysql 根据输入值 为基础的 环形排序
    时间范围内的按时间统计的每日数据填充
    记一次vue发版,在nginx下不乱码,在IIS下乱码的奇葩经历
    处理webflux 项目 增加 content-path
    java stream 不执行转换 不执行 管道中的操作
    增加一个spring mvc 的枚举转换器
  • 原文地址:https://www.cnblogs.com/bxd123/p/10729447.html
Copyright © 2020-2023  润新知