動態規劃 Help Jimmy

2021-10-02 10:18:55 字數 4457 閱讀 8014

場景中包括多個長度和高度各不相同的平台,地面是最低的平台,高度為零,長度無限,jimmy老鼠在時刻 0 從高於所有平台的某處開始下落,它的下落速度始終為1公尺/秒,當jimmy落到某個平台上時,遊戲者選擇讓它向左還是向右跑,它跑動的速度也是1公尺/秒,當jimmy跑到平台的邊緣時,開始繼續下落,jimmy每次下落的高度不能超過max公尺,不然就會摔死,遊戲也會結束,設計乙個程式,計算jimmy到底地面時的最早時間

第一行是測試資料的組數t(0 <= t <= 20)

每組測試資料的第一行是四個整數 n,x,y,max,用空格分隔

n是平台的數目(不包括地面)

x 和 y 是jimmy開始下落的位置的橫豎座標

max是一次下落的最大高度

接下來的n行每行描述乙個平台,包括三個整數,x1[ i ],x2[ i ] 和 h[ i ]

h[ i ]表示平台的高度

x1[ i ] 和 x2[ i ]表示平台左右端點的橫座標

1 <= n <= 1000,-20000 <= x,x1[i], x2[i] <= 20000,0 < h[i] < y <= 20000(i = 1..n)

補充:所有座標的單位都是公尺,jimmy的大小和平台的厚度均忽略不計,如果jimmy恰好落在某個平台的邊緣,被視為落在平台上,所有的平台均不重疊或相連,測試資料保證問題一定有解

對輸入的每組測試資料,輸出乙個整數,jimmy到達地面時的最早時間

input13

817200

108010

134143

output

23

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define _for(i,a,b) for(int i=a;i#define _unfor(i,a,b) for(int i=a;i>=b;i--)

#define ri(a) scanf("%d",&a)

#define mset(a,val,n) for(int i=0;i#define mset2(a,val,n,m) for(int i=0;i#define fi freopen("d:\\in.txt","r",stdin)

#define fo freopen("d:\\out.txt","w",stdout)

using

namespace std;

typedef

long

long ll;

/*-------下面為主要**-------*/

const

int n=

1005

;const

int m=

20005

;struct time //定義結構體

a[n]

;int dp[n+2]

[2];

// 0:表示第i的木板左邊到底部的最短時間

// 1: 表示第i的木板右邊到底部的最短時間

int n,x,y,max_h;

intcmp

(time c,time b)

//排序函式

void

left

(int i)

//左 k++;}

if(a[i]

.h-a[k]

.h>max_h)

dp[i][0

]=int_max;

else

//這裡的else是最有靈魂的地方:成敗都在這

dp[i][0

]=a[i]

.h;//因為它下面沒木板,直接落地

}void

right

(int i)

//右 k++;}

if(a[i]

.h-a[k]

.h > max_h)

//不能到達下一平台

dp[i][1

]=int_max;

else

dp[i][1

]=a[i]

.h;//因為它下面沒木板,直接落地

}int

main()

int time=

min(dp[0]

[0],dp[0]

[1])

;//取最小值

printf

("%d\n"

,time)

;//輸出結果

}return0;

}

**的簡潔程度取決於對題目的理解程度,下面我說一些對本題的理解

1、場景中包括多個長度和高度各不相同的板子(平台),說明所有板子都是上下參差不齊的,寫**時不用考慮同一平面優先到哪一塊板子,只用考慮不同高度優先下降到哪一塊板子

2、貪心思路:下降到距離差更大的板子,這咋一看沒問題,但這只是當前狀態最優解,而不是整體最優解(如下圖,明顯第一條路是最優解)

3、採用下降一層回頭看一層的策略,由下圖距離

從三層出發,到二層,回頭看第三層,可以算出時間是

二、三層高度差 + 三層左側距離(設為 t1),再到一層,回頭看第二層和第三層,第一種時間是 t1 + 二層右側距離 + 一二層高度差,第二種時間是一層右側距離+一三層高度差,最後取最小就得出到達第一層所用時間的最優解

那麼我們可以模擬一下,若有很多層,每一層的時間就為t + 回頭看的層數左或右側距離 + 回頭看的層數與本層數高度差,而 t 即回頭看的那層到最頂層所用的最優時間,再取最小值,因此這樣就可以得出到達最底層所用時間的最優解

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define _for(i,a,b) for(int i=a;i#define _unfor(i,a,b) for(int i=a;i>=b;i--)

#define ri(a) scanf("%d",&a)

#define mset(a,val,n) for(int i=0;i#define mset2(a,val,n,m) for(int i=0;i#define fi freopen("d:\\in.txt","r",stdin)

#define fo freopen("d:\\out.txt","w",stdout)

using

namespace std;

typedef

long

long ll;

/*-------下面為主要**-------*/

const

int n=

1005

;//最大層數

const

int m=

20005

;//絕對值最大座標

struct time

a[n]

;//n層板子

int dp[n]

;//代表當前當前層到最頂層的最短時間

int n,x,y,max_h;

intcmp

(time c,time b)

//排序函式

void

back

(int i)

if(a[k]

.x2 >= a[i]

.x1 && a[k]

.x2 <= a[i]

.x2)

if(i==0)

dp[i]

=max

(tmp1,tmp2)

; k++

;//再回頭看上一層}}

intmain()

printf

("%d\n"

,dp[0]

);}return0;

}

動態規劃(二) Help Jimmy 滑雪

if 板子k左端正下方沒有別的板子 else if 板子k左端正下方的板子編號是m 實現 poj1661 help himmy 這樣效率太低了,一早上沒看幾個題 要是不是特別好看懂,先把偽 寫出來就比較好懂了 分析 將板子由高到低按從0到n編號,起始點的為0 不妨認為jimmy開始的位置是乙個編號為...

POJ1661Help Jimmy(動態規劃)

description help jimmy 是在下圖所示的場景上完成的遊戲。場景中包括多個長度和高度各不相同的平台。地面是最低的平台,高度為零,長度無限。jimmy老鼠在時刻0從高於所有平台的某處開始下落,它的下落速度始終為1公尺 秒。當jimmy落到某個平台上時,遊戲者選擇讓它向左還是向右跑,它...

poj 1661 Help Jimmy 動態規劃

題意 給n個用左端點 右端點 高度標識的平台,問乙個下落速度,移動速度均為1的點下落到地面的最小時間,其中每次下落距離不能超過輸入值max.分析 動態規劃ldp i 表示從第i塊木板左邊下落到地面的最小時間,rdp i 表示從第i塊木板右邊下落到地面的最小時間。poj 1661 sep9 inclu...