• P1514 引水入城


    P1514 引水入城

       先看一下线段覆盖的贪心

     

     

     

    【解析】

      这道题有两问

    (1)能否满足要求

    (2)蓄水厂/干旱地有几个

    对于第一问,我们可以从第一行的每一个城市出发 dfs 一下它可以走到的所有点,标记,这样的话,如果不能满足要求的话,第 n 行一定会有没有被标记的点

    这样就hin好办辣,算一算几个点没有被标记,第二问就OK辣

    如果满足要求的话,就hin不好办辣

    实际上第一行的每个点最后可以到达第 n 行,水流过的城市是一个连续的区间(详见楼上蟹蟹)

    那么就可以用区间覆盖(详见楼上蟹蟹)来做辣

    l[x][y]表示点(x,y)可以到达的区间最左端

    r[x][y]表示点(x,y)可以到达的区间最右端

    【代码】

    #include<bits/stdc++.h>
    
    using namespace std;
    
    int n,m;
    int high[505][505],l[505][505],r[505][505];
    bool vis[505][505];
    int dx[4]={1,-1,0,0int dy[4]={0,0,1,-1};
    
    void dfs(int x,int y)
    {
        vis[x][y]=true;
        for(int i=0;i<=3;i++)
        {
            int xx=x+dx[i];
            int yy=y+dy[i];
            
            if(xx<1||xx>n||yy<1||yy>m)  continue ;
    if(high[xx][yy]>=high[x][y]) continue;
    if(!vis[xx][yy]) dfs(xx,yy);           //见注释
      
            l[x][y]=min(l[x][y],l[xx][yy]);
            r[x][y]=max(r[x][y],r[xx][yy]);
        }
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        
        memset(vis,false,sizeof(vis));
        memset(l,0x3f,sizeof(l));
        memset(r,0,sizeof(r));
    for(int i=1;i<=n;i++)
          for(int j=1;j<=m;j++)
          scanf("%d",&high[i][j]);
          
        for(int i=1;i<=m;i++)
          l[n][i]=r[n][i]=i;
        
        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)
        {
            printf("0
    ");
            printf("%d",cnt);
            return 0;
        }
        
    //区间覆盖
    int left=1; cnt=0; while(left<=m) { int right=0; for(int i=1;i<=m;i++) if(l[1][i]<=left) right=max(right,r[1][i]); left=right+1; cnt++; } printf("1 "); printf("%d",cnt); return 0; }

    【注释】

            if(xx<1||xx>n||yy<1||yy>m)  continue ;
            if(high[xx][yy]>=high[x][y]) continue;
            if(!vis[xx][yy]) dfs(xx,yy);

    等价于

    bool pan(int x,int y)
    {
        return x>=1&&x<=n&&y>=1&&y<=m;
    }
    
    if((pan(xx,yy))&&(high[x][y]>high[xx][yy]))
     {
            if(!vis[xx][yy])
               dfs(xx,yy);
               
            l[x][y]=min(l[x][y],l[xx][yy]);
            r[x][y]=max(r[x][y],r[xx][yy]);
     } 

    由于无论[xx][yy]是否被dfs过,都要用 L[xx][yy] R[xx][yy]来更新L[x][y] R[x][y]

    所以要 if 套 if 

     在此感谢rqy神仙  QVQ喵喵喵

    一开始咱也不知道那个错的为啥不行  咱也不问  

    后来咱问了 咱就会啦

     

  • 相关阅读:
    vue-if,vue-show,vue-for指令
    vue计算属性与监听器
    vue属性绑定和双向数据绑定
    C#将JSON文本转换成HttpResponseMessage数据行
    C#数据表(DataTable)转键值对集合
    C# .ToString()格式大全
    C#图片动画效果(旋转360度)异步
    C#利用鼠标绘图
    C#模拟键盘键操作
    C#显示和隐藏鼠标
  • 原文地址:https://www.cnblogs.com/xiaoyezi-wink/p/10927283.html
Copyright © 2020-2023  润新知