模板篇 k短路 SDOI2010 魔法豬學院

2021-08-15 06:33:32 字數 2728 閱讀 9806

都成了一道模板題了ovo

不想看的自行點目錄

今天才發現自己還沒有學a*

就去看了一下a*尋路, 但是只看也不行啊, 得找題練一練啊..

然後上luogu搜a*演算法結果找到了這道題?

但這不應該是道圖論麼= =

然後看了看題解發現原來是最短路預處理然後a*

那就寫嘛, 寫的有模有樣的大約30min?

然後過了樣例, 交上去30pts, 其餘re..

然後改陣列大小再交 40pts mle…

蛤? 然後又改一遍, 40pts re…

什麼鬼咯… 然後發現自己根本tm沒呼叫dij()這個函式…

也就是沒預處理, 直接搜的, 突然覺得40pts很不錯了2333

然後呼叫dij()就開始恆輸出0了. 結果發現剛開始要反向建邊?

然後就xjb改, 因為怕mle還刪掉一些陣列重複利用之類的…

後來終於又過了樣例 然後交上去0pts 9wa1re…

emmmm又是什麼鍋啊…

冷靜分析了一波, 發現自己dij往裡加點的時候是這麼加的:

hp[sz++]=(zt);
這tm還能過樣例??????????

然後改完就能70pts re了.

然後改一兩波陣列大小就終於ac了.

然而要是省選幹出這種事就死透了.. 最多通過對拍搞個70吧? (沒準直接m掉滾粗了emmmm

好了吐槽時間結束, 我們來看看這道題.

都說了是k短路模板, 題意就是求1->n的前k短路的長度和不超過m, 求最大的k.

我們就進行bfs, 第k次搜到n搜到的就是最短路.

但是樸素的bfs很顯然是過不了的, 我們要採用啟發式搜尋(a*).

感覺a*好像比數論什麼的要有用... 現實生活中用到a*的場合也是非常多的, 比如遊戲中角色的自動尋路啊之類的都要用到a*不是...(然後再吐槽一句在markdown裡打多個a*的話會出現玄學的斜體...

a*的基本形式: f(x)=g(x)+h(x), 其中

- f(x)表示從起始狀態到結束狀態的估價

- g(x)表示從起始狀態到當前狀態已經花費的代價.

- h(x)自然就是表示從當前狀態到結束狀態的估價咯~

其中a*演算法的核心就是乙個合適的h(x)的選擇.

- 如果h(x)比實際值要小, 那麼能得到最優解, 但是搜尋範圍較大, 效率較低.

- 如果h(x)比實際值要大, 那麼搜尋範圍較小, 速度快, 但不一定能取得最優解.

- 而如果h(x)恰好等於實際值, 那麼搜尋將按照最優解進行, 是我們最想看到的一種情況.

- 所以我們要盡可能讓自己選的h(x)接近實際值.

很幸運的是, 在k短路這個問題中, 我們剛好能取到完美地等於實際值的h(x),

我們只需要把邊反向, 從終點開始求一波單源最短路就ok了.. (而且好像這題不卡spfa…

a*的過程中總是要找到f值最小的優先進行擴充套件, 我們就寫個堆就好了..

這裡傾情推薦algorithm庫里的push_heap和pop_heap函式, 不管開不開o2都快的飛起, 比手寫堆都快, 不知道怎麼實現的.

(而且這題據說用priority_queue會mle的說~

我們每次搜到n就用e減去這條路的長度, 如果e<0就輸出當前的k就好了.

怎麼說呢 這題還不能算是特別正宗的a*, 因為也不需要記錄什麼openset closeset, 也不需要輸出路徑所以不需要記錄父親之類的, 所以就這樣吧…

#include 

#include

#include

using

namespace

std;

const

int n=5050;

const

int m=2e5+8;

struct edgee[m]; int v[n],tot;

inline

void buildedge(const

int&x,const

int&y,const

double&z)

struct zthp[m<<3]; int sz;

inline

bool

operator

<(const zt&a,const zt&b)

double d[n],z[m],k; int n,m,x[m],y[m];

void dij();

while(sz);

::push_heap(hp, hp+sz);}}

}int astar(int s=0);

while(sz);

::push_heap(hp, hp+sz);

}if(x.x==n)

}return s;

}int main() dij();

::memset(e, 0, sizeof e);

::memset(v, 0, sizeof v); tot=0;

for(int i=1;i<=m;++i)

::buildedge(x[i], y[i], z[i]);

printf("%d",astar());

}

以後陣列算著空間夠的話陣列一定能開大就開大….

當然還是一定要避免mle… 畢竟陣列開小了還能得個部分分, mle就直接爆零滾粗了(ノ`д)ノ

SDOI2010 魔法豬學院(K短路)

ipig在假期來到了傳說中的魔法豬學院,開始為期兩個月的魔法豬訓練。經過了一周理論知識和一周基本魔法的學習之後,ipig對豬世界的世界本原有了很多的了解 眾所周知,世界是由元素構成的 元素與元素之間可以互相轉換 能量守恆 能量守恆 ipig 今天就在進行乙個麻煩的測驗。ipig 在之前的學習中已經知...

SDOI2010 最短路 大陸爭霸

我們將每個節點的最短距離記錄為如下兩個量 arr 和 into 分別代表達到當前點的最短距離和滿足當前節點前置條件的最短距離,最短距離在兩者中取大值。然後硬跑最短路就行了。include include include include define maxn 300005 define maxm 7...

大陸爭霸 SDOI2010 帶限制最短路

只要你有無限個自爆機械人,你就能為所欲為 斯普林 布拉澤 題目描述 略一句話題意 傑森國有 n 個城市,由 m 條單向道 路連線。傑森國的首都是城市 n 你只需摧毀傑森國首都就能獲勝。為了盡量減小己方的消耗,你決定使用自爆機械人完成這一任務。唯一的困難是,傑森國的一部分城市有結界保護,不破壞掉結界就...