引水入城(NOIP2010提高组)

版权声明:本文为博主原创文章,转载请注明出处:http://blog.csdn.net/cggwz https://blog.csdn.net/cggwz/article/details/83213174

黑子传送服务

首先bfs记录那些点可达,然后判断是否可以完全覆盖,如果不可以,统计一下没有覆盖的点的数量输出。
如果可以,有两条性质,第一,每一个河边城市可以到达的干旱城市一定是连续的,第二,对于每一个河边城市能到达的干旱城市区间,他们的区间首段是有序的,即从左到右递增。
所以我们在之前的bfs中要记录每个点可达的河边城市左右端点,然后用贪心进行区间覆盖问题即可。
代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
int mapp[505][505];
int vis[505][505];
int l[505][505],r[505][505];
int ans;
void scan(int x,int y){
	if(x>=(n+1)||x<=0||y<=0||y>=(m+1)){
		return;
	}
	if(vis[x][y]){
		return;
	}
	vis[x][y]=1;
	if(x-1>=1&&mapp[x][y]>mapp[x-1][y]){
		scan(x-1,y);
		l[x][y]=min(l[x][y],l[x-1][y]);
		r[x][y]=max(r[x][y],r[x-1][y]);
	}
	if(y-1>=1&&mapp[x][y]>mapp[x][y-1]){
		scan(x,y-1);
		l[x][y]=min(l[x][y],l[x][y-1]);
		r[x][y]=max(r[x][y],r[x][y-1]);
	}
	if(x+1<=n&&mapp[x][y]>mapp[x+1][y]){
		scan(x+1,y);
		l[x][y]=min(l[x][y],l[x+1][y]);
		r[x][y]=max(r[x][y],r[x+1][y]);
	}
	if(y+1<=m&&mapp[x][y]>mapp[x][y+1]){
		scan(x,y+1);
		l[x][y]=min(l[x][y],l[x][y+1]);
		r[x][y]=max(r[x][y],r[x][y+1]);
	}
}
int main(){
	scanf("%d%d",&n,&m);
	memset(mapp,0x3f,sizeof(mapp));
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			scanf("%d",&mapp[i][j]);
		}
	}
	memset(vis,0,sizeof(vis));
	memset(l,0x3f,sizeof(l));
	memset(r,0,sizeof(r));
	for(int i=1;i<=m;i++){
		l[n][i]=r[n][i]=i;
	}
	for(int i=1;i<=m;i++){
		if(vis[1][i]==0){
			scan(1,i);
		}
	}
	int flag=1;
	int num=0;
	for(int i=1;i<=m;i++){
		if(vis[n][i]==0){
			flag=0;
			num++;
		}
	}
	printf("%d\n",flag);
	if(flag==0){
		printf("%d",num);
		return 0;
	}
	ans=0;
	int ind=1;
	while(ind<=m){
		int cur=0;
		for(int i=1;i<=m;i++){
			if(l[1][i]<=ind){
				cur=max(cur,r[1][i]);
			}
		}
		ind=cur+1;
		ans++;
	}
	printf("%d",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/cggwz/article/details/83213174