这道题的答题思路分两部分,一呢是先要判断能不能覆盖最后一行,二呢是要求最优值。
第一步呢好办,可以flag设标记,然后最后一行遍历一遍看看是否都为真,如果不是,那么输出不可以, 否则进行第二步
我们可以利用l和r的两维数组,代表i行j列的水库能管到左边最远哪里,右边最远哪里,然后在第一行进行查找遍历,因为只有第一行能够建立水库,所以就over了。
大体思路就是这样,具体的ac代码程序我贴出来了
#include<bits/stdc++.h>
using namespace std;
int n;
int m;
int a[501][501];
int flag[501][501];
int l[501][501];
int r[501][501];
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};
void dfs(int x,int y)
{
flag[x][y]=1;
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(a[xx][yy]>=a[x][y]) continue;//不能运水
if(flag[xx][yy]==0) 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()
{
cin>>n>>m;
memset(l,0x3f,sizeof(l));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
if(i==n) l[i][j]=r[i][j]=j;//干旱区
}
}
memset(flag,0,sizeof(flag));
for(int i=1;i<=m;i++)
{
if(flag[1][i]==0) dfs(1,i);//从第一行扩展 ,这里flag一定要判断,因为可能之前都已经扩展到了,就没必要再一次扩展了
}
int ok=1;
int ans=0;
for(int i=1;i<=m;i++)
{
if(flag[n][i]==0)
{
ok=0;
ans++;
}
}
if(ok==0)
{
cout<<ok<<endl<<ans;
return 0;
}//不行的那种情况
else
{
int lef=1;
int rig=r[1][1];
while(lef<=m)
{
for(int i=1;i<=m;i++)
{
if(l[1][i]<=lef)
{
rig=max(rig,r[1][i]);//查看最右端能到达哪里,作为下一个水库的开始的左边
}
}
lef=rig+1;//下一个水库的开始
ans++;
}
}
cout<<1<<endl<<ans;
return 0;
}