vijos1777 引水入城

描述

在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠。该国的行政区划十分特殊,刚好构成一个N行M列的矩形,其中每个格子都代表一座城市,每座城市都有一个海拔高度。

为了使居民们都尽可能饮用到清澈的湖水,现在要在某些城市建造水利设施。水利设施有两种,分别为蓄水厂和输水站。蓄水厂的功能是利用水泵将湖泊中的水抽取到所在城市的蓄水池中。因此,只有与湖泊毗邻的第1行的城市可以建造蓄水厂。而输水站的功能则是通过输水管线利用高度落差,将湖水从高处向低处输送。故一座城市能建造输水站的前提,是存在比它海拔更高且拥有公共边的相邻城市,已经建有水利设施。

由于第N行的城市靠近沙漠,是该国的干旱区,所以要求其中的每座城市都建有水利设施。那么,这个要求能否满足呢?如果能,请计算最少建造几个蓄水厂;如果不能,求干旱区中不可能建有水利设施的城市数目。

格式

输入格式

输入文件的每行中两个数之间用一个空格隔开。

输入的第一行是两个正整数N和M,表示矩形的规模。

接下来N行,每行M个正整数,依次代表每座城市的海拔高度。

输出格式

输出有两行。如果能满足要求,输出的第一行是整数1,第二行是一个整数,代表最少建造几个蓄水厂;如果不能满足要求,输出的第一行是整数0,第二行是一个整数,代表有几座干旱区中的城市不可能建有水利设施。

样例1

样例输入1[复制]

 
2 5
9 1 5 4 3
8 7 6 1 2

样例输出1[复制]

 
1
1

限制

每个测试点1s

提示

本题共有10个测试数据,每个数据的范围如下表所示:
测试数据编号 能否满足要求 N M
1 不能 ≤ 10 ≤ 10
2 不能 ≤ 100 ≤ 100
3 不能 ≤ 500 ≤ 500
4 能 = 1 ≤ 10
5 能 ≤ 10 ≤ 10
6 能 ≤ 100 ≤ 20
7 能 ≤ 100 ≤ 50
8 能 ≤ 100 ≤ 100
9 能 ≤ 200 ≤ 200
10 能 ≤ 500 ≤ 500
对于所有的10个数据,每座城市的海拔高度都不超过10^6。

来源

noip2010提高组复赛

 
好久没有发题解了啊……
这是NOIP之前复习的时候做的原题
首先从上到下一遍bfs,判断是否有不能被覆盖的城市
这样做完保证一定有解了
然后一个蓄水厂能覆盖的城市一定是一个连续的区间(反证法)
因此再从下到上一遍bfs算出每个蓄水厂能覆盖的城市的左右端点
然后变成线段覆盖了……贪心搞掉
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<ctime>
#define LL long long
#define inf 0x7ffffff
#define pa pair<int,int>
#define pi 3.1415926535897932384626433832795028841971
using namespace std;
const int mx[4]={1,0,-1,0};
const int my[4]={0,1,0,-1};
inline LL read()
{
    LL x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,m,t,w,len;
int a[510][510];
int l[510][510];
int r[510][510];
bool mrk[510][510];
int qx[250010];
int qy[250010];
struct seg{
	int l,r;
}d[1000];
bool operator <(const seg &a,const seg &b)
{
	return a.l<b.l||a.l==b.l&&a.r<b.r;
}
inline void bfs1()
{
	while(t<w)
	{
		int nx=qx[++t];
		int ny=qy[t];
		for (int k=0;k<4;k++)
		{
			int wx=nx+mx[k],wy=ny+my[k];
			if (wx<1||wx>n||wy<1||wy>m||mrk[wx][wy])continue;
			if (a[wx][wy]>=a[nx][ny])continue;
			qx[++w]=wx;
			qy[w]=wy;
			mrk[wx][wy]=1;
		}
	}
}
inline void bfs2(int dat[510][510],int x,int y)
{
	t=0;w=1;
	qx[1]=x;
	qy[1]=y;
	dat[x][y]=y;
	while (t<w)
	{
		int nx=qx[++t];
		int ny=qy[t];
		mrk[nx][ny]=1;
		for (int k=0;k<4;k++)
		{
			int wx=nx+mx[k]; 
			int wy=ny+my[k];
			if (wx<1||wx>n||wy<1||wy>m||dat[wx][wy])continue;
			if (a[wx][wy]<=a[nx][ny])continue;
			dat[wx][wy]=dat[nx][ny];
			qx[++w]=wx;
			qy[w]=wy;
		}
	}
}
int main()
{
	n=read();m=read();
	for (int i=1;i<=n;i++)
	  for(int j=1;j<=m;j++)
	    a[i][j]=read();
	for (int i=1;i<=m;i++)
	{
		qx[++w]=1;
		qy[w]=i;
		mrk[1][i]=1;
	}
	bfs1();
	int tot=0;
	for (int i=1;i<=m;i++)
	  if (!mrk[n][i])tot++;
	if (tot)
	{
		printf("0
%d
",tot);
		return 0;
	}
	memset(mrk,0,sizeof(mrk));
	for (int i=1;i<=m;i++)if (!l[n][i])bfs2(l,n,i);
	for (int i=m;i>=1;i--)if (!r[n][i])bfs2(r,n,i);
	for (int i=1;i<=m;i++)
	  if (mrk[1][i])
	  {
	  	d[++len].l=l[1][i];
	  	d[len].r=r[1][i];
	  }
	sort(d+1,d+len+1);
	int now=0,ned=0,mx=0;
	for (int i=1;i<=len;i++)
	{
		if(d[i].l<=now+1)mx=max(mx,d[i].r);
		else now=mx,ned++,mx=max(mx,d[i].r);
	}
	if(now!=m)ned++;
	printf("1
%d
",ned);
}

  

——by zhber,转载请注明来源
原文地址:https://www.cnblogs.com/zhber/p/4093492.html