poj2486---Apple Tree(樹狀DP+揹包)
阿新 • • 發佈:2018-12-14
題意:一顆樹,n個點(1-n),n-1條邊,每個點上有一個權值,求從1出發,走V步,最多能遍歷到的權值。
思路:考慮到能從父節點走到某一個子節點後,在走回至父節點,再取走其他的子節點(所以這個地方有3種情況).另開一維陣列表示是否回到該結點。
dp[i][j][state]表示以i為父節點最多走j步,state表示狀態,是否回到該節點.
dp陣列初始化的時候,如果已經在i結點上了,那麼他不管走幾步起碼都是weight[i];
#include<iostream> #include<cstring> #include<vector> #define maxn 105 using namespace std; vector<int>edge[maxn]; int dp[maxn][maxn<<1+5][2]; ///dp[i][j][state]表示在子樹i中最多走j步。 ///state==0表示回到該點,否則不回. int n,m; int weight[maxn]; void dfs(int u,int father) { for(int i=0;i<=m;i++) dp[u][i][0]=dp[u][i][1]=weight[u]; for(int i=0;i<edge[u].size();i++) { int v=edge[u][i]; if(v==father) continue; dfs(v,u); for(int j=m;j>=1;j--)///揹包 { for(int k=0;k<j;k++)///區間更新 { ///1表示返回 if(j-k>=2){ dp[u][j][1]=max(dp[u][j][1],dp[v][k][1]+dp[u][j-k-2][1]); ///遍歷完其他子樹後回到u,在遍歷完v的子樹後返回v,返回u. dp[u][j][0]=max(dp[u][j][0],dp[v][k][1]+dp[u][j-k-2][0]); ///遍歷v的子樹,返回v,返回u再去遍歷其他子樹 } dp[u][j][0]=max(dp[u][j][0],dp[v][k][0]+dp[u][j-k-1][1]); ///遍歷完其他子樹後回到u,在遍歷v的子樹,不返回 } } } } int main() { while(cin>>n>>m) { memset(dp,0,sizeof(dp)); /// memset(weight,0,sizeof(weight)); for(int i=1;i<=n;i++) { edge[i].clear(); cin>>weight[i]; } for(int i=1;i<n;i++) { int u,v; cin>>u>>v; edge[u].push_back(v); edge[v].push_back(u); } dfs(1,0); /// cout<<dp[1][m][0]<<endl; cout<<max(dp[1][m][0],dp[1][m][1])<<endl; } return 0; }