^_^ o(∩∩)o...我去剛要打個哈哈出現這麼多顏文字還那麼醜
這題 算是 樹型dp經典的 小變種 了吧 。。
首先 理解一下 啥叫 樹型dp,
樹型樹型,告訴我們 這是一個 基於樹(二叉樹)結構的dp
那麼自然要有建樹的過程。
建樹 有 三種 1)單方向 2)鄰接表 3)孩子兄弟
再想到dp是自下ershang
故而先計算孩子節點資訊
利用孩子節點資訊算出根節點資訊
寫出狀態轉移方程
通常分為 葉子節點:dp[][]
非葉子節點: dp[i][]= blablabla
這道題的狀態轉移方程
考慮每個節點 i為根 的sizeK的子樹的最大 weight;
dp[i][sizeK]=max(dp[i][sizeK] , dp[i的孩子][sizeK-k]+dp[i][k]); ( sizeK= K ~ 1, k=sizeK~1);
最後 掃一遍 dp[i][題目指定子樹大小];
ok.
#include <iostream>#include <string.h>#include <vector>#define Max(a,b) (a)>(b)?(a):(b)using namespace std;const int maxn=110;int f[maxn][maxn],N,K,w[maxn];bool vis[maxn];vector<int> node[maxn];void dfs(int r){int size=node[r].size(),i,j,t;f[r][0]=0;f[r][1]=w[r];for(i = 0;i < size; i++){j=node[r][i];dfs(j);for(j = K;j >= 1; j--){for (t = j; t>=1; t--) {f[r][j]=Max(f[r][j],f[r][t]+f[j][j-t]);}}}}int main(void){while(cin>>N>>K){int i;for (i = 0; i < N ; i++) {cin>>w[i];node[i].clear();}int a,b;memset(vis,0,sizeof(vis));memset(w,0,sizeof(w));for (i = 1; i < N; i++) {cin>>a>>b;node[a].push_back(b);vis[b]=true;}for(i = 0;i < N && vis[i] ;i++);dfs(i);int ans=0;for (i = 0; i < N; i++) {if(f[i][K]>ans) ans=f[i][K];}cout<<ans<<endl;}return 0;}