題解 poj1947 樹形DP

2021-08-22 19:41:28 字數 1016 閱讀 5008

題目鏈結

dp[root][j]:以root為根節點的子樹,得到 j 個節點的子樹需要最少減掉的邊數,注意子樹中必須保留root節點。否則無法dp

那麼很明顯的邊界條件dp[root][1] = num(兒子的個數),因為要只剩乙個節點的子樹,那麼所有的孩子都減掉,這樣就為兒子的個數。

那麼狀態轉移方程呢

dp[root][i] = min(dp[root][i-k]+dp[child][k] - 1,dp[root][i]);

其實就是要得到乙個i個節點的子樹,列舉所有的孩子為k個節點的,當前root保留 i-k 個節點,然後把root和child之間之前被剪斷的連線起來,所以這裡要減1

注意非根節點的答案要加一

#include

#include

#include

#include

const

int n=200;

using

namespace

std;

int num[n];//num[i]表示i節點的子節點個數

int sum[n];//sum[i]以i為根的樹的所有節點個數

int dp[200][200];//dp[i][j]以i為根的樹還剩j個節點所刪去邊的最小值

vector

v[200];//v[x][y]x與y相連

void dfs(int root)

for(int i=0;i//列舉root的子節點

}int main()

for(i=1;i<=n;i++)

dp[i][1]=num[i];//將子節點全部刪完

dfs(1);

int ans=dp[1][p];

for(i=2;i<=n;i++)//掃瞄找最小值

ans=min(ans,dp[i][p]+1);//漏了+1,把根節點和父節點斷開

printf("%d\n",ans);

return

0;}

POJ 1947 樹形DP入門題

給出n個點,n 1個關係,建出樹形圖,問最少減去幾個邊能得到節點數為p的樹。典型樹形dp題 dp cur j 記錄cur結點,要得到一棵j個節點的子樹去掉的最少邊數 轉移方程用的揹包的思想 對當前樹的每乙個子樹進行計算 砍掉此子樹 dp cur j dp cur j 1 不砍掉 for l 0 l ...

POJ 1947 樹DP獲得冠軍

特定n點,n 1的關係。建立了一棵樹,問至少減去幾個邊緣節點可以被作為得到p樹。樹典型dp稱號 dp cur j 記錄cur節點,為了得到乙個j除去該子樹的節點的邊的最小數目 對當前樹的每個子樹進行計算 砍掉此子樹 dp cur j dp cur j 1 不砍掉 for l 0 l j l dp c...

POJ1947 樹狀DP 揹包問題

cpp0.cpp created on 2014年7月8日 author miao include include include include using namespace std vectorv 155 int dp 155 155 int n,p const int inf 0xfffff...