樹上揹包 POJ2486 Apple Tree

2021-07-22 14:23:41 字數 1464 閱讀 9830

一棵樹n(<=100)個節點,每個節點有a[i]個蘋果,從1出發走k(<=200)步,問最多能得到多少個蘋果。

首先想到每個節點只有3種情況,要麼不經過,要麼經過了最後回來,要麼經過了最後不回來,只用關心後兩種就行。

於是可以想到乙個dp[i][j][k],表示從i出發走j步,k=0表示回來,k=1表示不回來,現在想怎麼轉移。

轉移的關鍵是每個子節點走多少步,暴力列舉顯然是不行的。

不過仔細想想每個子節點都可以0~k-1(要回來就是k-2)步,也就是說要把這k步分配到所有子節點上,可以聯想到分組揹包,每個節點的0~k-1步為一組,每組內只能選1個,組與組之間沒有限制,揹包容量是k,然後就可以寫出轉移了。

對rt的乙個子節點v:

列舉剩餘容量j:

枚舉子節點走的步數l: dp

[rt]

[j][

0]=m

ax(d

p[rt

][j]

[0],

dp[r

t][j

−l][

0]+d

p[v]

[l−2

][0]

) dp

[rt]

[j][

1]=m

ax(d

p[rt

][j]

[1],

dp[r

t][j

−l][

0]+d

p[v]

[l−1

][1]

) dp

rt][

j][1

]=ma

x(dp

[rt]

[j][

1],d

p[rt

][j−

l][1

]+dp

[v][

l−2]

[0])

然後就解決了。

//

// main.cpp

// 2486

//// created by 翅膀 on 16/9/9.

//#include

#include

#include

#include

using

namespace

std;

const

int n = 105;

int a[n], n, k;

vector

g[n];

int dp[105][205][2];

void dfs(int rt, int f)}}

}int main(int argc, const

char * argv)

dfs(1, 0);

printf("%d\n", max(dp[1][k][0], dp[1][k][1]));

}return

0;}

POJ2486 Apple Tree 樹上揹包

一句話題意 一棵樹,一共n個點,每個點上有乙個權值,求從1出發,走k步,最多能遍歷到的權值。可以往回走。第一 二 道樹上揹包題,先是看了dalao的題解,改了一點就過樣例了。然而.tle?改了挺久發現由於多組資料且沒有 0 0 的輸入,如果不在讀入的時候加 或 eof 就會死迴圈,從而導致tle。狀...

每日一題 POJ 2486 樹形dp 樹上揹包

並不難寫,關鍵是要想清楚。樹形dp的第乙個比較完整寫完的題,是比較經典的題,來紀念一下。一開始沒想清楚是因為對揹包問題的滾動陣列優化的理解不夠,自然在樹上的問題也沒思考清楚。同時因為每個case過後忘記清零,導致re了一發,以後需要注意。dpr是回到該點,nr是不回到該點,轉移方程如 ac 耗時18...

樹上揹包練習

p2014 ctsc1997 選課 p2014 ctsc1997 選課 solution 樹上揹包模板題 因為有多節課是沒有先修課的,所以並不是只有一棵樹,用乙個0號點作為沒有先修課的課程的先修課,這樣就合併成了一棵樹,只要選取m 1個點 必選0 即可。轉移方程 dp u j max dp u j ...