一棵樹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 ...