洛谷 P1514 引水入城(DFS)

题目链接:https://www.luogu.com.cn/problem/P1514

注意这道题只能用DFS而不能直接用dp,因为在每一个格子,没有固定的方向,而是上下左右都可以走。但其中有dp的思想:不断更新l和r。

这道题中首先判断干旱区所有的城市能否都能建有水利工程。则先让第一行的每一个城市都有水利工程,然后进行遍历,看最后一行的所有点能不能都被走到,如果有走不到的,则说明不行,记录走不到的个数,输出即可。

如果都能走到,则需要考虑第一行选哪几个使得能将最后一行全部覆盖过来。那么在刚才遍历的时候,可以不断更新l[][],r[][](详见代码),直到从l[n][]和r[n][]更新至l[1][]和r[1][]。现在l[1][i]和r[1][i]中分别存第一行第i个如果选的话,能灌溉最后一行[l,r]这个区间的城市。然后用线段覆盖思想来做即可。(详见while)

AC代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 using namespace std;
 5 const int N=505;
 6 int n,m;
 7 int vis[N][N],g[N][N],l[N][N],r[N][N];
 8 int _x[4]={1,0,0,-1};
 9 int _y[4]={0,1,-1,0};
10 bool judge(int x,int y){
11     if(x<1||x>n) return 0;
12     if(y<1||y>m) return 0;
13     return 1;
14 }
15 void DFS(int x,int y){
16     vis[x][y]=1;
17     for(int i=0;i<4;i++){
18         int xx=x+_x[i],yy=y+_y[i];
19         if(!judge(xx,yy)) continue;
20         if(g[xx][yy]>=g[x][y]) continue;
21         if(!vis[xx][yy]) DFS(xx,yy);
22         l[x][y]=min(l[x][y],l[xx][yy]);
23         r[x][y]=max(r[x][y],r[xx][yy]);
24     }
25 }
26 int main(){
27     memset(l,0x3f3f3f,sizeof(l));
28     scanf("%d%d",&n,&m);
29     for(int i=1;i<=n;i++)
30     for(int j=1;j<=m;j++) scanf("%d",&g[i][j]);
31     for(int i=1;i<=m;i++) l[n][i]=r[n][i]=i;
32     for(int i=1;i<=m;i++) if(!vis[1][i]) DFS(1,i);
33     int flag=0,ans=0;
34     for(int i=1;i<=m;i++){
35         if(!vis[n][i]){
36             flag=1;
37             ans++;
38         }
39     }
40     if(flag){
41         printf("0
%d",ans);
42         return 0;
43     }
44     int low=1;
45     while(low<=m){
46         int maxx=0;
47         for(int i=1;i<=m;i++){
48             if(l[1][i]<=low) maxx=max(maxx,r[1][i]);
49         }
50         ans++;
51         low=maxx+1;
52     }
53     printf("1
%d",ans);
54     return 0;
55 }
AC代码
原文地址:https://www.cnblogs.com/New-ljx/p/13849813.html