P1514 [NOIP 2010 提高组] 引水入城
题目
传送门
思路
经过思考可以发现一个水流到最后一行的覆盖必是一个连续的线段。对于最后一行没有标记的格子直接统计并输出即可。如果有解那么我们每次寻找每个点的左边界和右边界,也就是他们最多可以到达的地方。
代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
int l[505][505];
int r[505][505];
int a[505][505];
bool vis[505][505];
int fx[6]={0,1,0,-1};
int fy[6]={1,0,-1,0};
void dfs(int x,int y){
vis[x][y]=1;
for(int i=0;i<4;i++){
int tx=x+fx[i];
int ty=y+fy[i];
if(tx<1||ty<1||tx>n||ty>m||a[x][y]<=a[tx][ty])continue;
if(!vis[tx][ty])dfs(tx,ty);
l[x][y]=min(l[x][y],l[tx][ty]);
r[x][y]=max(r[x][y],r[tx][ty]);
}
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
memset(l,0x3f,sizeof(l));
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
if(i==n){
l[i][j]=j;
r[i][j]=j;
}
}
}
for(int i=1;i<=m;i++){
if(!vis[1][i])dfs(1,i);
}
int ans=0;
for(int i=1;i<=m;i++){
if(!vis[n][i]){
ans++;
}
}
if(ans){
cout<<0<<'\n'<<ans;
return 0;
}
int left=1,right=r[1][1];
while(left<=m){
for(int i=1;i<=m;i++){
if(left>=l[1][i]){
right=max(right,r[1][i]);
}
}
left=right+1;
ans++;
}
cout<<1<<'\n'<<ans;
return 0;
}

浙公网安备 33010602011771号