洛谷 P1514 引入水域(貪心線段覆蓋 DP)

2021-09-27 02:48:40 字數 1966 閱讀 8645

題目大意:

在乙個n*m棋盤中,我們把源放在第一行,源可以對外進行bfs種子填充,問:為了使得最後一行被填充完畢,我們最少需要在第一行放多少個源。假如最後一行不能被填充,問我們不能填充的個數。

解題思路:

首先,最後一行不能被填充十分簡單,我們只需要在第一行逐列放源,假如最後一行還是有不能被覆蓋的點的話,證明不能被填充完畢。

現在關鍵是第一問,最少放幾個源。

結論1:當我們已知能夠完全覆蓋最後一行時。當源開始做flood fill,假若能覆蓋到最後一行,那麼覆蓋到的最後一行必定是乙個完整的區間(即不會產生覆蓋了 [ 0,3]  [5 ,7]的情況)可以用反證法證明。

所以,當我們可以求出第一行中每一列的能到達最後一列的區間的範圍,然後我們判斷最少需要多少個區間就能把最後一行覆蓋。

首先,我們求第一行的每一列的所屬區間範圍。最簡單的方法是,我們重複做bfs,但是複雜度過了,最後會t。

這裡我們用dp的方法。

for nr in r_c_neighbour

memol[r][c]=min(memol[nr][nc])

其中memol[r][c]表示r,c這個點能夠到達的最後一行的最左邊的點的位置。nr,nc表示r,c的四鄰域

同樣的for nr in r_c_neighbour

memor[r][c]=max(memor[nr][nc])

其中memor[r][c]表示r,c這個點能夠到達的最後一行的最右邊的點的位置。nr,nc表示r,c的四鄰域

那這裡還有乙個問題,邊界是什麼:

很顯然,當我們走到最後一行時,若某一格不能再dfs下去了,那麼我們認為這是我們能走的最後乙個位置。

寫的時候注意:

(1)首先有一些點可能是到達不了最後一行的,注意這些點的狀態的賦值。不要因為錯誤的賦值,使得轉移方程出錯

(2)在dfs中,我們很重要的一環是防止走重複,在這裡我們注意有兩種走重複,一種是memo已經賦值的了,那麼我們返回memo即可,另外則是memo還未賦值,這時候我們同樣需要返回。

關於區間覆蓋:

這是一種貪心的做法,我們從最左邊的端點開始,要保證能夠把最左邊的點覆蓋。然後,我們選擇能夠覆蓋最左邊的點中的區間能夠達到最右的區間,每次都這樣貪心選取。

#include using namespace std;

const int maxn=510;

int chess[maxn][maxn];

pairmemo[maxn][maxn];

int vis[maxn][maxn];

int n,m;

const int dr=;

const int dc=;

pairdfs(int r,int c)

if(vis[r][c]==1)return make_pair(-1,-1);

vis[r][c]=1;

int fir=1e9;

int sec=-1;

for(int i=0;i<4;i++)

memo[r][c].first=fir;

memo[r][c].second=sec;

if(r==n-1 && memo[r][c].first>c)memo[r][c].first=c;

if(r==n-1 && memo[r][c].second>n>>m;

for(int i=0;i>chess[i][j];

} for(int i=0;ifor(int j=0;jmemset(vis,0,sizeof(vis));

for(int i=0;iint flag=0;

int cnt=0;

for(int i=0;i} if(flag)

int lf=0;

cout<<1

while(lf<=m-1)

} assert(maxr!=-1);

lf=maxr+1;

} cout

}

洛谷 P1514 引水入城

題目描述 在乙個遙遠的國度,一側是風景秀美的湖泊,另一側則是漫無邊際的沙漠。該國的行政區劃十分特殊,剛好構成乙個n 行m 列的矩形,如上圖所示,其中每個格仔都代表一座城市,每座城市都有乙個海拔高度。為了使居民們都盡可能飲用到清澈的湖水,現在要在某些城市建造水利設施。水利設施有兩種,分別為蓄水廠和輸水...

洛谷 P1514 引水入城

題目概述 給定乙個n m的矩陣,每個格仔代表高度,水只能向低處流。從最上面一排倒水,問最下面一排的每個格仔是否都有水流過。若是,輸出最少需在幾個格仔上倒水,若否,則輸出最下面一排有幾個格仔接不到水。解題思路 可以證明,如果底排每個格仔都有水,那麼從頂部每個格仔倒下的水,在底部形成的一定是乙個連續的區...

洛谷P1514 引水入城

想用搜尋水一水,結果一水就是一下午emmm 用第一層的點去更新其他層的點,並記錄能更新到的最遠的端點,然後下面判斷是否最底層都能到達,都能到達就通過記錄的左右端點來更新,使在最少使用的情況下框到最大的範圍就行了 by acermo include include include include in...