BJWC2008 雷濤的小貓

2022-05-09 15:05:44 字數 1668 閱讀 1558

嘟嘟嘟

dp。剛開始我想的是dp[i][j]表示在第 i 棵樹上,高度為h能吃到的最多的果子,如此能得到轉移方程: dp[i][j] = max(dp[i][j + 1], dp[k][j + derta]) (k = 1~n && k != i)。但因為這樣寫會導致dp[k][j + derta] (k > i)的部分沒有更新,所以應該把dp試的兩胃交換一下。這樣dp方程就能正常轉移了:

dp[i][j] = max(dp[i + 1][j], max(dp[i + derta][k]) (k = 1~n && k != j) ) 

然而這樣的時間複雜度是o(h * n * n)的,過不了。

優化:觀察 max(dp[i + derta][k]) (k = 1~n && k != j),實際上我們就是在高度為i + derta 的所有狀態中取乙個max,所以可以開乙個陣列max[i]代表高度為 i 時dp[i][j]的最大值,然後每一次求完dp[i][j]時動態更新max[i]即可。所以轉移方程就變成了

dp[i][j] = max(dp[i +1][j], max[i +derta])

時間複雜度o(h * n)。

1 #include2 #include3 #include4 #include5 #include6 #include7 #include8 #include9 #include10 #include11

using

namespace

std;

12#define space putchar(' ')

13#define enter puts("")

14#define mem(a) memset(a, 0, sizeof(a))

15 typedef long

long

ll;16 typedef double

db;17

const

int inf = 0x3f3f3f3f;18

const db eps = 1e-8;19

const

int max_hig = 2e3 + 5;20

const

int maxn = 5e3 + 5;21

inline ll read()

2226

while(isdigit(ch))

27if(last == '

-') ans = -ans;

28return

ans;29}

30 inline void

write(ll x)

3136

37int

n, h, d;

38int

a[max_hig][maxn], dp[max_hig][maxn], max[max_hig];

3940

intmain()

4148

for(int i = h; i >= 0; --i)

49for(int j = 1; j <= n; ++j)

5056

int ans = 0;57

for(int i = 1; i <= n; ++i) ans = max(ans, dp[0

][i]);

58write(ans); enter;

59return0;

60 }

view code

洛谷 P1107 BJWC2008 雷濤的小貓

傳送門 這道題其實是道dpdp dp題,但至於它為什麼會被分到數論,那就不得而知了.首先我們設f i j f i j f i j 為到第i ii高度在第j jj棵樹上時,我們可以摘到的最多柿子數,那麼這時我們可以得到兩個方程 a j i a j i a j i 表示第i ii棵樹的第j jj高度上有...

洛谷 P1107 BJWC2008 雷濤的小貓

給出若干棵樹,以及每棵樹不同高度有幾個柿子的資訊。以及給出走法規則,求能夠獲取到最多的柿子數。我自己的方法是 設dp i j 表示第j棵樹,高度為i時獲得的最大值。然後三重迴圈遍歷一下,第三重迴圈的含義是從之前較高的樹上找出乙個最大的值 乙個最優解 如下 dp計算 for int i h delta...

洛谷P1107 BJWC2008 雷濤的小貓

題目鏈結 n 2dp比較好想,f i j 表示第i棵樹高度為j的最大收益 直接從上到下轉移即可,每次記錄下max f 1 n j 用於下面的轉移 f i j max f i j 1 max f 1 n j delta max f 1 n j delta 是已經求出來的,o 1 查詢 列舉j和i,總複...