poj 2486 (樹形dp (好題))

2021-06-16 14:27:41 字數 1355 閱讀 8884

最近做了些樹形dp的題目, 感覺對這種將每棵子樹都當做乙個物品處理的樹形揹包題目理解還不夠深刻, 果然這題就被破的很慘, 但好在想了很長時間想清楚了, 這題就是求從一顆帶點權樹的根節點出發, 走過k條邊能獲得的最大權值。 考慮某乙個節點u, 

肯定有一維狀態表示從該節點開始還可以走多少條邊, 但最優決策有可能是從u的某個子樹v1下去再上來再到另一棵子樹v2中, 所以我們可以定義狀態dp[u][j][0]表示從點u出發最多走j條邊並回到該點能獲得的最大權值, dp[u][j][1]則表示可以不回到該點的。。。

我們不難得到下面兩個轉移方程:

1. dp[u][j][0] = max(dp[u][j][0], dp[v][j - k - 2][0] + dp[u][k][0]); (k <= j && v是u的乙個子節點)

2. dp[u][j][1] = max(dp[u][j][1], dp[v][j - k - 1][[1] + dp[u][k][0]);

我一開始就是這樣做的結果wa了而且測了discuss中的資料也過了, 後來看到discuss中有人說少了乙個轉移就wa, 我就開始想是不是有問題, 後來成功造出了一組資料, 就發現問題了, 其實我們在最外層列舉u的子節點v, 轉移時的dp[u]***都是前i個子樹的狀態, 而且最後一維必須是0因為我們在考慮是否在當前這棵子樹繼續向下時必須使得在遍歷之前的子樹後回到點u, 但這樣就有可能丟失了最優決策, 因為最優決策有可能就是在之前已經轉移過的子樹中所以我們有第三個轉移

3.dp[u][j][1] = max(dp[u][j][1], dp[u][k][1] + dp[v][j - k - 2][0]);

另附一組資料

6 63 2 1 4 5 6

1 61 3

1 53 4

3 2ans: 19

#include #include #include #include #include #include #include using namespace std;

const int n = 105;

const int m = n << 1;

int head[n], next[m], to[m];

int w[n];

int dp[n][n << 1][2];

int tot, n, m;

void init()

tot = 0;

}void add(int u, int v)

void dfs(int u, int fa)

} }}int main()

dfs(1, 0);

printf("%d\n", dp[1][m][1]);

} return 0;

}

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

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

poj2486 Apple Tree 樹形dp揹包

題意 由n個結點組成的樹,每個結點有個點權,你從結點1出發,問最多走m步可以獲得點權和 重複走乙個結點只有第一次走過會 獲得點權值 的最大值。思路 設dp i j k 表示從i結點走j步 k 0表示回到i結點共j步,k 1表示j步之後不回到i節點 可獲得點權和的最大值。考慮當前的結點u,以及它的子結...

POJ 2342 樹形DP入門題

有乙個大學的慶典晚會,想邀請一些在大學任職的人來參加,每個人有自己的搞笑值,但是現在遇到乙個問題就是如果兩個人之間有直接的上下級關係,那麼他們中只能有乙個來參加,求請來一部分人之後,搞笑值的最大是多少。樹形dp入門題。dp部分 dp i 0 表示職員i不來參加party,以i為根的子樹的最大搞笑值,...