動態規劃法之蜘蛛俠救美記

2021-07-06 07:43:24 字數 2713 閱讀 7251

實驗周的題目,使用動態規劃法解決,感覺這個題目挺不錯的。因為動態規劃法用的不是很多,理解的也不是太透徹,所以把這道題目拿出來。

問題描述

章魚博士綁架了蜘蛛俠的女友喬丹把她關在西塔上,蜘蛛俠必須盡快到西塔去救她通過使用他的**——蜘蛛網。蜘蛛俠的公寓到塔之間有一條筆直的路,路旁有許多高大的建築物並且高度都不低於他的公寓。蜘蛛俠可以使用他的蜘蛛網到達大樓的另一邊,圖1顯示了蜘蛛俠從他的公寓到b,從b到c,從c到塔。所有的建築物(包括塔)被視為直線,並且在他划擺期間不能碰到地面這意味著蜘蛛網的長度不能大於建築物的高度,在蜘蛛俠劃擺期間不能倒退。

輸入要求:

輸入的第一行包含測試用例的數量k(1<=k<=20),每個案例都以乙個單獨的整數n開始,k表示建築物的數量,接下來的n行中每行包括兩個整數xi, yi, (0 <= xi, yi <= 1000000)表示建築物的位置和高度。第乙個建築是公寓而最後乙個建築是塔,以xi的值遞增輸入而且不重複輸入相同的xi的值。

輸出要求:

對於每乙個測試案例,輸出一行劃擺的最少次數,如果不能到達塔則輸出-1。

問題分析

對於公寓到塔的距離之間的任意乙個位置p,可以有多種方式到達該點,題目的要求是在到達終點的多種方式中選擇乙個劃擺次數最少的方式,這種在執行過程中不斷用得到的資料去更新目標資料的方法和動態規劃法有異曲同工之妙,所以本問題選擇使用動態規劃法來求解。

首先考慮的問題是對於任意乙個建築物ti(xi, yi),如果能夠從該塔進行劃擺,那麼此次劃擺的起點(xi-1,yi-1)與建築物ti(xi, yi)應該要滿足一定的關係式。

從題目的分析中可以得到,蜘蛛俠在划擺的過程中不能夠碰到地面,這個就意味著蜘蛛網的長度不能夠大於建築物的高度,否則蜘蛛俠在划擺作圓周運動時因為半徑過長而碰到地面則不符合題意。又因為每一次的劃擺過程,不論其位置x為和值,其高度y必等於公寓的高度y0,這可以利用物理知識或者直接從圖1中可以看出來。這樣我們就可以求出划擺的起點(xi-1,yi-1)與建築物ti(xi, yi)之間滿足的關係式,如下:

這裡利用勾股定理來計算建築物ti的有效起點距離l,這裡的有效起點距離l如圖所示:

l的物理意義是凡是一次劃擺的起點在l之內,那麼都可以從建築物ti完成乙個劃擺。這也成為判斷蜘蛛俠是否可以滑到終點塔的依據。如果有任意一次的劃擺不滿足這樣的條件,那麼就可以輸出-1認為無法到達終點而不用再繼續執行程式。

當得到任意乙個建築物ti的有效起點距離之後,那麼在該距離之內的所有點都將對建築物ti之後的點產生影響,即根據距離之內的點的值去修改建築物之後的距離的值。這裡我們使用swing[xi]來表示在xi之前已進行的劃擺次數,同時我們取建築物ti的有效起點距離l之內的乙個點j(xj,y0),從點j開始進行劃擺,當劃過建築物ti之後所達到的點d(xd,yd)滿足如下的關係式:

那麼swing[xd]的值按理就應該是swing[xj]+1,因為從點j進行了一次劃擺到達了點d。但是按照前面所說,到達點d的方式可能存在很多種,我們需要的只是其中劃擺次數最少的一次,所以在修改swing[xd]的值之前我們首先應該做的是判斷swing[xd]當前的值與swing[xj]+1的大小,如果swing[xj]+1的值小於swing[xd]的值,那麼我們就應該修改它,表示從點j進行劃擺到達點d所需要的總共劃擺次數是當前最少的。

從開始我就說明了此次演算法採用的是動態規劃法的框架,根據前面的執行結果去修改當前的值的做法在修改swing[xd]的值的時候得到了很好的體現,這也證明了我採用演算法是基本正確的。

既然是動態規劃法,那麼就一定存在乙個狀態轉移方程,當前值的修改是在滿足狀態轉移方程的條件下進行修改,從前面的分析就可以很容易寫出關於swing[xd]的狀態轉移方程了。

得到了狀態轉移方程之後,我們對每乙個建築物都進行求解得到有效起點距離,然後對距離之內的每乙個點按照狀態轉移方程來修改swing[xd]的值,當所有的建築物都考慮之後,那麼我們直接看swing[xn]的值即可。如果swing[xn]的值為-1則表示不能到達終點,反之得到的乙個整數值就是從公寓到塔所劃擺的最少次數。

動態規劃法的使用條件是當前的值是前面所有結果共同作用的,動態的去修改的值,因為此題的swing[xn]的求解滿足該條件,所以動態規劃法的分析方法是求解此題的關鍵所在。

原始碼參考

#include

using

namespace

std;

#include

#define max 5000

#define max_swing 2000001

int x[max],y[max],t,n,distance[max], swing[max_swing];

int getcount();

int min(int a,int b)

for(int j=0;j1;

cout

int getcount()

}return swing[x[n-1]];

}

動態規劃法之移位解碼問題

前言 同學找我看看一段不到90行的 我從下午2點多收到 但是直到6點多才完全看懂。可能因為之前沒有看題目就直接看 所以直接上手就比較痛苦,花的時間也就比較長了。自我安慰中 題目描述 題目是一道acm題,當時看的時候只有15 的通過率,所以也屬於比較難的題目了。題目的意思大概意思是 移位密碼是一種將訊...

演算法學習系列之 動態規劃法

早上起來,看了一道美團面試題,是關於動態規劃的。突然發現對學過的演算法並沒有乙個系統全面的認識。於是準備把經典演算法以寫部落格的形式回顧一遍。貴在堅持!如果問題是由交疊的子問題構成的,我們就可以運用動態規劃技術來解決它。一般來說,這樣的子問題出現在對給定問題求解的遞推關係中,這個遞推關係中包含了相同...

找零問題之動態規劃法求解Python

遞迴是從後往前逐步判斷求解,17元有哪個和哪個組成,而哪個又由 和 組成,其實除了遞迴求解,也可以換種思路,從前往後逐步遞推。從小到大都求出來最優解,逐步遞推。而大的最優解一定包含某個小的最優解 注意是某乙個,這個是不確定的,用反證法 如果不包含,那必定還有乙個解,這個解和最優解一定有乙個是最優的,...