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

为了使居民们都尽可能饮用到清澈的湖水,现在要在某些城市建造水利设施。水利设施有两种,分别为蓄水厂和输水站。蓄水厂的功能是利用水泵将湖泊中的水抽取到所在城市的蓄水池中。
因此,只有与湖泊毗邻的第1 行的城市可以建造蓄水厂。而输水站的功能则是通过输水管线利用高度落差,将湖水从高处向低处输送。故一座城市能建造输水站的前提,是存在比它海拔更高且拥有公共边的相邻城市,已经建有水利设施。由于第N 行的城市靠近沙漠,是该国的干旱区,所以要求其中的每座城市都建有水利设施。那么,这个要求能否满足呢?如果能,请计算最少建造几个蓄水厂;如果不能,求干旱区中不可能建有水利设施的城市数目。
输入格式
每行两个数,之间用一个空格隔开。输入的第一行是两个正整数N,M,表示矩形的规模。接下来N行,每行M个正整数,依次代表每座城市的海拔高度。
输出格式
两行。如果能满足要求,输出的第一行是整数1,第二行是一个整数,代表最少建造几个蓄水厂;如果不能满足要求,输出的第一行是整数0,第二行是一个整数,代表有几座干旱区中的城市不可能建有水利设施。
样例

此题,作为在变成六题的前一年的最后一题,应该是当时最难得QAQ,果然,我看题目都用了好久才理解题目,题意大致就是在第一行建几个蓄水场,让他往最下面那一行城市输水,而且可能科技没有那么发达,所以只能靠着天然的地势来输水,用高度差来输水(真的不想去吐槽,连个输水机都没有)回归正题,既然要考高度差来输水,而且明确的说明了在第一行,明显的dfs或bfs,从第一行开始dfs遍历一下然后进行标记,再判断一下最后一行是否被全部遍历到了,这样第一问就轻松地结束了;第二问就比较难了,如果可以的话也是比较好判断的,先说一下我的思路,我没有去实现QAQ,就是可以就一下第一行有几个点被dfs了,也就是dfs会标记点嘛,第一次dfs标记1,第二次标记2,第i次标记i,到最后看一下有几次标记应该就好了。我感觉是可以的QAQ,但是题解里搞的是线段覆盖QAQ,就是最后一行标记一下,从1……n,在dfs回溯时一个取min,一个取max,到最后找一下有几个线段就好了,感觉跟我的思路差不多(好像还比我的难),我也没试我的思路,也不知道对不对,咱啥也不知道,啥也不敢说QAQ
代码
#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f;
const int dx[4]={0,0,+1,-1};
const int dy[4]={+1,-1,0,0};
int v[520][520],op1[520][520],op2[520][520];
int a[520][520];
int ans=0;
int n,m;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void dfs(int x,int y)
{
v[x][y]=1;
for(int i=0;i<4;i++)
{
int xx=dx[i]+x,yy=dy[i]+y;
if(a[x][y]<=a[xx][yy]||xx<1||xx>n||yy<1||yy>m)
continue;
if(!v[xx][yy])
dfs(xx,yy);
op1[x][y]=min(op1[xx][yy],op1[x][y]);
op2[x][y]=max(op2[xx][yy],op2[x][y]);
}
}
int main()
{
n=read();
m=read();
memset(op1,inf,sizeof(op1));
memset(op2,0,sizeof(op2));
memset(v,0,sizeof(v));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
a[i][j]=read();
}
for(int i=1;i<=m;i++)
op1[n][i]=op2[n][i]=i;
for(int i=1;i<=m;i++)
{
if(!v[1][i])
dfs(1,i);
}
bool p=0;
// for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=m;j++)
// {
// cout<<op1[i][j]<<' ';
// }
// cout<<endl;
// }
// cout<<endl;
// for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=m;j++)
// {
// cout<<op2[i][j]<<' ';
// }
// cout<<endl;
// }
for(int i=1;i<=m;i++)
{
if(!v[n][i])
{
p=1;
ans++;
}
}
if(p)
{
printf("0\n%d\n",ans);
return 0;
}
else
{
int ll=1,maxx=0;
while(ll<=m)
{
int maxx=0;
for(int i=1;i<=m;i++)
{
if(op1[1][i]<=ll)
{
maxx=max(maxx,op2[1][i]);
}
}
ans++;
ll=maxx+1;
}
}
printf("1\n%d\n",ans);
return 0;
}
