Memory search + greedy - WOJ # 1838 water into the city

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/weixin_42557561/article/details/102742516

Portal


Analysis

The key point of this question is that a very important conclusion:
each water plant in a continuous interval must be able to cover the bottom of

With this nature, we can get memory search leftmost point and the rightmost point of each water plant can cover, then greed can be covered at least segment

As for me, Han Han.
Just think of the n- 3 practices
for each water plant bfs, recording the lowest point reached under it
and then you can not do memory of, do not cover the line
would have been thinking about the idea of processing each store with a similar backpack water, but no progress and
fundamental research did not find that important properties of the above!


Code
#include<bits/stdc++.h>
#define in read()
#define re register
using namespace std;
inline int read(){
	char ch;int f=1,res=0;
	while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
	while(ch>='0'&&ch<='9'){
		res=(res<<1)+(res<<3)+(ch^48);
		ch=getchar();
	}
	return f==1?res:-res;
}
const int N=505;
int n,m,h[N][N],l[N][N],r[N][N];
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
bool vis[N][N]; 
void DFS(int x,int y){
	vis[x][y]=1;
	for(re int i=0;i<4;++i){
		int xx=x+dx[i];
		int yy=y+dy[i];
		if(xx<1||xx>n||yy<1||yy>m) continue;
		if(h[xx][yy]>=h[x][y]) continue;
		if(!vis[xx][yy]) 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(){
	n=in;m=in;
	for(re int i=1;i<=n;++i) for(re int j=1;j<=m;++j) h[i][j]=in;
	memset(l,127,sizeof(l));
	memset(r,0,sizeof(r));
	for(re int i=1;i<=m;++i) l[n][i]=r[n][i]=i;
	for(re int i=1;i<=m;++i) if(!vis[1][i]) DFS(1,i);
	int cnt=0;
	for(re int i=1;i<=m;++i) if(!vis[n][i]) cnt++;
	if(cnt){printf("0\n%d",cnt);return 0;}
	int L=1,R=0;
	while(L<=m){
		for(re int i=1;i<=m;++i)
			if(l[1][i]<=L) R=max(R,r[1][i]);
		cnt++;
		L=R+1;
	}
	printf("1\n%d",cnt);
	
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_42557561/article/details/102742516