題目如上
非常非常巧妙的一道題目;
1.先思考,要求的是什麼?
如題目所說,目的是要把第n排全部建上那個什麼水利工程,全建上,也就是全部覆蓋!再考慮起點,也就是河岸,動動筆,也不難發現,某些節點可以拓展到終點的一片區域,
如樣例一中9可以拓展到的點如圖所示,
綠色的框則表示9,也就是入口第一列的這個點所能到達的出口範圍,這裡叫做他能管轄的範圍;
理解到這一步,應該很明顯了,要求覆蓋所有終點所需要的起點最少,故覆蓋完終點所需要的管轄區間最少。
over 完美的變成了區間覆蓋問題!
不了解區間覆蓋問題的可以參考
2.如何求解??
這裡用的貪心,但我用的動態規劃;
設f[i][j]為覆蓋完區間i–j所需要最少的起點數,dp[i]表示覆蓋完1–i所需要最少的起點數,故dp[m]為最終答案;
每個起點所管轄的區域如何求呢?
非常明顯,搜尋**—bfs!!你想非主流用dfs也沒人管你。。。
每個第一行的點開始寬搜,搜到最後一行也就是終點更新管轄區域。
那麼問題也就迎刃而解了nice!!!ig,nb!!!!
**注釋也不少,應該較好理解
#include
#include
#include
#include
#include
#include
using
namespace std;
int n,m,dp[
510]
,f[510][
510]
,e[510][
510]
,out[
510]
,vis[
510]
[510
],cx[5]
=,cy[5]
=;struct ini[
510]
;//第i個起點的管轄區域l--r,v表示該七點是否被其他起點所搜到,如果被其他起點能到達,該起點就沒暖用了。。
struct node
;void
bfs(
int sy));
while
(!q.
empty()
)//更新管轄區域 if(
!vis[xx]
[yy]
) q.
push
((node)
),vis[xx]
[yy]=1
;}}}
}int
main()
//判斷特例,不可能覆蓋完
memset
(dp,
0x7f
,sizeof
(dp));
memset
(f,0x7f
,sizeof
(f))
;for
(int k=
1;k<=m;k++)}
}//初始化
for(
int i=
1;i<=m;i++
)for
(int j=
1;j) dp[i]
=min
(dp[i]
,dp[j]
+f[j+1]
[i])
;//dp開始!
printf
("%d\n%d\n",1
,dp[m]);
//over!
return0;
//ig nb!!!
}
就喜歡短小精悍的**,關注一下謝謝了!!! LUOGU P1514 引水入城 bfs
傳送門 解題思路 拉了很長的戰線,換了好幾種寫法終於過了。首先每個蓄水場一定是對沙漠造成連續一段的貢獻,所以可以 bfs 出每種狀態,然後做一次最小區間覆蓋,但這樣的複雜度有點高。就每次只搜那些比左右高的點。include include include include include includ...
P1514 引水入城
先用dfs搜尋,從最上面的一行往下拓展,所有點拓展完後,掃瞄最後一行是否有沒被染上色的,有則說明 不能滿足要求 如果沒有,在用dfs,計算出最上面一行的每個點 大於等於兩邊的點 能拓展到的最左端和最右端,然後就轉化成了區間覆蓋問題。區間覆蓋問題是給你幾個區間,然後給你乙個大區間,用盡量少的小區間來覆...
luogu1514 引水入城
題目描述 在乙個遙遠的國度,一側是風景秀美的湖泊,另一側則是漫無邊際的沙漠。該國的行政區劃十分特殊,剛好構成乙個n 行m 列的矩形,如上圖所示,其中每個格仔都代表一座城市,每座城市都有乙個海拔高度。為了使居民們都盡可能飲用到清澈的湖水,現在要在某些城市建造水利設施。水利設施有兩種,分別為蓄水廠和輸水...