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\n");
        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\n"); 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喵喵喵

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

后来咱问了 咱就会啦

 

posted @ 2019-05-26 20:04  晔子  阅读(267)  评论(0编辑  收藏  举报