引水入城NOIP

题面描述

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

为了使居民们都尽可能饮用到清澈的湖水,现在要在某些城市建造水利设施。水利设施有两种,分别为蓄水厂和输水站。蓄水厂的功能是利用水泵将湖泊中的水抽取到所在城市的蓄水池中。

因此,只有与湖泊毗邻的第1 行的城市可以建造蓄水厂。而输水站的功能则是通过输水管线利用高度落差,将湖水从高处向低处输送。故一座城市能建造输水站的前提,是存在比它海拔更高且拥有公共边的相邻城市,已经建有水利设施。由于第N 行的城市靠近沙漠,是该国的干旱区,所以要求其中的每座城市都建有水利设施。那么,这个要求能否满足呢?如果能,请计算最少建造几个蓄水厂;如果不能,求干旱区中不可能建有水利设施的城市数目。

输入格式

每行两个数,之间用一个空格隔开。输入的第一行是两个正整数N,M,表示矩形的规模。接下来N行,每行M个正整数,依次代表每座城市的海拔高度。

输出格式

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

样例

此题,作为在变成六题的前一年的最后一题,应该是当时最难得QAQ,果然,我看题目都用了好久才理解题目,题意大致就是在第一行建几个蓄水场,让他往最下面那一行城市输水,而且可能科技没有那么发达,所以只能靠着天然的地势来输水,用高度差来输水(真的不想去吐槽,连个输水机都没有)回归正题,既然要考高度差来输水,而且明确的说明了在第一行,明显的dfs或bfs,从第一行开始dfs遍历一下然后进行标记,再判断一下最后一行是否被全部遍历到了,这样第一问就轻松地结束了;第二问就比较难了,如果可以的话也是比较好判断的,先说一下我的思路,我没有去实现QAQ,就是可以就一下第一行有几个点被dfs了,也就是dfs会标记点嘛,第一次dfs标记1,第二次标记2,第i次标记i,到最后看一下有几次标记应该就好了。我感觉是可以的QAQ,但是题解里搞的是线段覆盖QAQ,就是最后一行标记一下,从1……n,在dfs回溯时一个取min,一个取max,到最后找一下有几个线段就好了,感觉跟我的思路差不多(好像还比我的难),我也没试我的思路,也不知道对不对,咱啥也不知道,啥也不敢说QAQ

代码

#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f;
const int dx[4]={0,0,+1,-1};
const int dy[4]={+1,-1,0,0};
int v[520][520],op1[520][520],op2[520][520];
int a[520][520];
int ans=0;
int n,m;
inline int read(){
   int s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}
void dfs(int x,int y)
{
	v[x][y]=1;
	for(int i=0;i<4;i++)
	{
		int xx=dx[i]+x,yy=dy[i]+y;
		if(a[x][y]<=a[xx][yy]||xx<1||xx>n||yy<1||yy>m)
		continue;
		if(!v[xx][yy])
		dfs(xx,yy);
		op1[x][y]=min(op1[xx][yy],op1[x][y]);
		op2[x][y]=max(op2[xx][yy],op2[x][y]);
	}
}
int main()
{
	n=read();
	m=read();
	memset(op1,inf,sizeof(op1));
	memset(op2,0,sizeof(op2));
	memset(v,0,sizeof(v));
	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++)
	op1[n][i]=op2[n][i]=i;
	for(int i=1;i<=m;i++)
	{
		if(!v[1][i])
		dfs(1,i);
	}
	bool p=0;
//	for(int i=1;i<=n;i++)
//    {
//    	for(int j=1;j<=m;j++)
//    	{
//    		cout<<op1[i][j]<<' ';
//    	}
//    	cout<<endl;
//    }
//    cout<<endl;
//    for(int i=1;i<=n;i++)
//    {
//    	for(int j=1;j<=m;j++)
//    	{
//    		cout<<op2[i][j]<<' ';
//    	}
//    	cout<<endl;
//    }
	for(int i=1;i<=m;i++)
	{
		if(!v[n][i])
		{
			p=1;
			ans++;
		}
	}
	if(p)
	{
		printf("0\n%d\n",ans);
		return 0;
	}
	else
	{
		int ll=1,maxx=0;
		while(ll<=m)
		{
			int maxx=0;
			for(int i=1;i<=m;i++)
			{
				if(op1[1][i]<=ll)
				{
					maxx=max(maxx,op2[1][i]);
				}
			}
			ans++;
			ll=maxx+1;
		}
	}
	printf("1\n%d\n",ans);
	return 0;
}

留下评论

通过 WordPress.com 设计一个这样的站点
从这里开始