P1514 引水入城

来源:互联网 发布:商品降价提醒软件 编辑:程序博客网 时间:2024/04/27 20:09

题目描述

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

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

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

输入输出格式

输入格式:

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

输出格式:

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


注意到一个城市建蓄水厂,那么它能供给的沙漠城市一定要是连续的一段区间,否则无解,很容易证明--

枚举每个城市建立蓄水厂,BFS搜索能覆盖的区间,剩下就是给出一堆区间,询问最少需要多少个区间能把[1,n]覆盖

贪心解决

注意特判n == 1时,不然有个数据刚好卡掉

#include<iostream>#include<cstdio>#include<queue>#include<vector>#include<bitset>#include<algorithm>#include<cstring>#include<map>#include<stack>#include<set>#include<cmath>#include<ext/pb_ds/priority_queue.hpp>using namespace std;const int maxn = 555;const int INF = ~0U>>1;const int dx[4] = {0,1,0,-1};const int dy[4] = {1,0,-1,0};struct Point{int x,y;Point(){}Point(int x,int y): x(x),y(y){}};int n,m,cnt,h[maxn][maxn],rig[maxn],vis[maxn][maxn];bool flag = 1,bo[maxn];queue <Point> Q;void BFS(int x,int y){vis[x][y] = ++cnt;Q.push(Point(x,y));int L = INF,R = 0;if (n == 1) L = R = y;while (!Q.empty()) {Point k = Q.front(); Q.pop();for (int i = 0; i < 4; i++) {int xx = k.x + dx[i];int yy = k.y + dy[i];if (xx < 1 || xx > n || yy < 1 || yy > m) continue;if (vis[xx][yy] == cnt || h[xx][yy] >= h[k.x][k.y]) continue;vis[xx][yy] = cnt;Q.push(Point(xx,yy));if (xx == n) L = min(L,yy),R = max(R,yy);}}for (int i = 1; i <= m; i++)if (vis[n][i] == cnt) bo[i] = 1;if (L != INF) rig[L] = max(rig[L],R);} int main(){#ifdef DMCfreopen("DMC.txt","r",stdin);#endifcin >> n >> m;for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++)scanf("%d",&h[i][j]);for (int j = 1; j <= m; j++)if (h[1][j] >= h[1][j-1])BFS(1,j);for (int j = 1; j <= m; j++)if (!bo[j]) flag = 0;if (!flag) {puts("0");int tot = 0;for (int j = 1; j <= m; j++)if (!bo[j]) ++tot;cout << tot;}else {puts("1");int pos = rig[1],ans = 1;while (pos < m) {int Nex = 0;for (int i = 1; i <= pos + 1; i++)Nex = max(Nex,rig[i]);++ans; pos = Nex;}cout << ans;}return 0;}

0 0
原创粉丝点击