Luogu P1514 引水入城
阿新 • • 發佈:2018-07-04
using 格子 () mat 通過 queue 一行 code 城市 行的城市靠近沙漠,是該國的幹旱區,所以要求其中的每座城市都建有水利設施。那麽,這個要求能否滿足呢?如果能,請計算最少建造幾個蓄水廠;如果不能,求幹旱區中不可能建有水利設施的城市數目。
題目描述
在一個遙遠的國度,一側是風景秀美的湖泊,另一側則是漫無邊際的沙漠。該國的行政區劃十分特殊,剛好構成一個 \(N\) 行 \(\times M\) 列的矩形,如上圖所示,其中每個格子都代表一座城市,每座城市都有一個海拔高度。
為了使居民們都盡可能飲用到清澈的湖水,現在要在某些城市建造水利設施。水利設施有兩種,分別為蓄水廠和輸水站。蓄水廠的功能是利用水泵將湖泊中的水抽取到所在城市的蓄水池中。
因此,只有與湖泊毗鄰的第\(1\)行的城市可以建造蓄水廠。而輸水站的功能則是通過輸水管線利用高度落差,將湖水從高處向低處輸送。故一座城市能建造輸水站的前提,是存在比它海拔更高且擁有公共邊的相鄰城市,已經建有水利設施。由於第 \(N\)
輸入樣例#1
2 5
9 1 5 4 3
8 7 6 1 2
輸出樣例#1
1
1
輸入樣例#2
3 6
8 4 5 6 4 4
7 3 4 3 3 3
3 2 2 1 1 2
輸出樣例#2
1
3
說明
【樣例1 說明】
只需要在海拔為 99 的那座城市中建造蓄水廠,即可滿足要求。
【樣例2 說明】
上圖中,在 3 3 個粗線框出的城市中建造蓄水廠,可以滿足要求。以這 3 3 個蓄水廠為源頭在幹旱區中建造的輸水站分別用3 種顏色標出。當然,建造方法可能不唯一。
數據範圍
思路
乍一看貌似只能打暴力,於是不顧一切的開始淦
但是結果很感人啊
後來想起來,之前學姐講過這個題。
但是當時並沒有好好聽課,so還是不會,我就開始想啊
好像是要用貪心來啊
但是咋貪是個問題
於是我繼續看題目
最下面的圖片讓我記起來了咋做
我們先用一個普通的\(DFS\)來判斷第\(N\)行的所有點能否引水入城在確定能夠滿足題目要求之後
我們來想一下。這樣的一張滿足要求的圖,第一行的每一個點的水所能流到的最後一行的點必然是一個區間
為什麽?
我可以告訴你我不知道啦啦啦啦
那麽將第一行每一個點能夠放水的城市就可以用BFS變成了一個區間,然後做一個區間覆蓋就能得出答案了
代碼
#include <iostream> #include <cstring> #include <cstdio> #include <queue> #include <algorithm> const int maxn = 503; using namespace std; int n, m, h[maxn][maxn], nownode, Ans, tot; bool vis[maxn][maxn], book[maxn], hhh; int dx[6] = {1, 0, -1, 0}; int dy[6] = {0, 1, 0, -1}; struct edge { int l, r; }ed[maxn]; struct node { int x, y; }; queue<node> Q; bool cmp(edge a, edge b) { if(a.l != b.l) return a.l < b.l; return a.r > b.r; } void BFS(node now) { while(!Q.empty()) { now = Q.front(); Q.pop(); int x = now.x, y = now.y; if(x == n) { ed[nownode].l = min(ed[nownode].l, y); ed[nownode].r = max(ed[nownode].r, y); } for(int i=0; i<4; i++) { int xx = dx[i]+x, yy = dy[i]+y; if(!vis[xx][yy] && xx <= n && xx > 0 && yy <= m && yy > 0 && h[xx][yy] < h[x][y]) { Q.push((node) {xx, yy}); vis[xx][yy] = 1; } } } } void dfs(int x, int y) { if(x == n) { ++tot; } for(int i=0; i<4; i++) { int xx = dx[i]+x, yy = dy[i]+y; if(h[xx][yy] < h[x][y] && !vis[xx][yy] && xx > 0 && yy > 0 && xx <= n && yy <= m) { vis[xx][yy] = 1; dfs(xx, yy); } } } int main() { scanf("%d%d", &n, &m); for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { scanf("%d", &h[i][j]); } } for(int i=1; i<=m; i++) { dfs(1, i); } if(tot < m) { printf("0\n%d", m-tot); return 0; } for(int i=1; i<=m; i++) { nownode = i; ed[nownode].l = 2147483647; ed[nownode].r = 0; while (!Q.empty()) Q.pop(); memset(vis, 0, sizeof(vis)); vis[1][i] = 1; Q.push((node) {1, i}); BFS(Q.front()); } sort(ed+1, ed+1+m, cmp); int cur = 0, nur = 0; Ans = 0; for(int i=1; i<=m; i++) { if(ed[i].l > m) break; if(ed[i].l <= cur+1) nur = max(ed[i].r, nur); else { cur = nur; Ans++; nur = max(nur, ed[i].r); } } if(cur != m) Ans++; printf("1\n%d", Ans); return 0; }
Luogu P1514 引水入城