LuoguP1514引水入城(搜尋 dp)

2021-08-30 11:36:17 字數 1923 閱讀 7905

題目如上

非常非常巧妙的一道題目;

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 列的矩形,如上圖所示,其中每個格仔都代表一座城市,每座城市都有乙個海拔高度。為了使居民們都盡可能飲用到清澈的湖水,現在要在某些城市建造水利設施。水利設施有兩種,分別為蓄水廠和輸水...