#include <cstdio>
#include <cstring>
using namespace std;
int n,m,nm[505][505],vis[505][505];
int l[505][505],r[505][505];
/*
搜索当前点是否能到达目的点 并且回溯标记
l数组为 某个蓄水厂 走过的所有的城市的 最小 标记 能走到最左边的哪个 最靠近沙漠的城市
r数组为 某个蓄水厂 能走过的所有城市的 最大 标签 能走到最右边的哪个 最靠近沙漠的城市
初始化:最靠近的一排城市 l 和 r 从1-m
*/
int xx[4]={-1,0,1,0};
int yy[4]={0,1,0,-1};
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a>b?b:a;}
void dfs(int x,int y){
vis[x][y]=true;
for(int i=0;i<4;i++){
int xa=x+xx[i];
int ya=y+yy[i];
if(xa<1||xa>n||ya<1||ya>m)continue;
if(nm[xa][ya]>=nm[x][y])continue;
if(!vis[xa][ya])dfs(xa,ya);
l[x][y]=min(l[x][y],l[xa][ya]);
r[x][y]=max(r[x][y],r[xa][ya]);
}
}
int main(){
scanf("%d%d",&n,&m);
memset(vis,0,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",&nm[i][j]);
for(int i=1;i<=m;i++)l[n][i]=r[n][i]=i;
for(int i=1;i<=m;i++)dfs(1,i);
bool sf=false;
int cnt=0;
for(int i=1;i<=m;i++){
if(!vis[n][i]){
sf=true;
cnt++;
}
}
if(sf){
printf("0\n%d",cnt);
return 0;
}
/*
按照题目要求,如果水无法流到每一个 接近沙漠的那一排城市中 ,则 输出 0 表示不能全部 流入
然后输出有多少个城市 没有流入水
*/
int left=1;
/*
如:数据
3 6
8 4 5 6 4 4
7 3 4 3 3 3
3 2 2 1 1 2
l数组输出
1 2 2 2 5 5
1 2 2 4 5 5
1 2 3 4 5 5
r数组输出
2 2 4 5 5 6
2 2 4 4 5 6
2 2 4 4 5 6
初始值left为1
查找第一行 也就是接近湖泊的那一行 看看有蓄水池的水能到达 最接近 沙漠的城市 的 1号城市
如有 ,则看当前蓄水池能最多流到多少个最接近沙漠的城市 =>r数组
然后left更新至left+1,也就是表示 将要 求 是否有蓄水池 能流到left+1号城市
然后重复操作
*/
while(left<=m){
int mxr=0;
for(int i=1;i<=m;i++)
if(l[1][i]<=left){
mxr=max(mxr,r[1][i]);
}
cnt++;
left=mxr+1;
}
printf("1\n%d",cnt);
return 0;
}
P1514 引水入城
2019-05-10