分類: 演算法
2012-07-01 21:53
494人閱讀收藏
舉報tree
output
input
struct演算法
description
有一棵蘋果樹,如果樹枝有分叉,一定是分2叉(就是說沒有只有1個兒子的結點)
這棵樹共有n個結點(葉子點或者樹枝分叉點),編號為1-n,樹根編號一定是1。
我們用一根樹枝兩端連線的結點的編號來描述一根樹枝的位置。下面是一顆有4個樹枝的樹
2 5\ /
3 4\ /
1現在這顆樹枝條太多了,需要剪枝。但是一些樹枝上長有蘋果。
給定需要保留的樹枝數量,求出最多能留住多少蘋果。
input
第1行2個數,n和q(1 <= q <= n,1 < n <= 100)。
n表示樹的結點數,q表示要保留的樹枝數量。接下來n-1行描述樹枝的資訊。
每行3個整數,前兩個是它連線的結點的編號。第3個數是這根樹枝上蘋果的數量。
每根樹枝上的蘋果不超過30000個。
output
乙個數,最多能留住的蘋果的數量。
sample input
5 21 3 1
1 4 10
2 3 20
3 5 20
sample output21
分析:這題的權值在邊上,這在思考時有些彆扭,其實只要把邊的權值轉移到兒子結點上,問題性質不變。
這樣狀態就應該容易想到了,f[i][j]表示以i結點為根的子樹保留j個結點所得的最大值。因為根結點沒有權值,所以我們要保留p+1個點。
f[i][j]=max{f[i_left][k]+f[i_right][j-1-k]} (0<=k<=j-1)
邊界 f[i][0]=0;f[i][1]=value[i]
最後f[1][p+1]就是答案
為什麼是j-1-k,而不是j-k呢?這是因為要保留以i為根的j個節點,而i已經佔了乙個節點了,所以孩子節點只能再保留j-1個節點了。
[cpp]view plain
copy
#include
#include
#include
using
namespace
std;
struct
node
tree[220];
intbool
vis[110];
intn,q;
void
make_tree(
introot)
//一旦涉及到樹的操作,遞迴總是會簡化很多**
} inttree_dp(
intt,
intk)
f[t][k]=0;
for(
inti=0;i<=k-1;i++)
f[t][k]+=tree[t].s;
return
f[t][k];
} int
main()
memset(tree,0,sizeof
(tree));
memset(vis,false
,sizeof
(vis));
make_tree(1);
memset(f,-1,sizeof
(f));
intans=tree_dp(1,q);
printf("%d\n"
,ans);
return
0;
}
在建樹的時候也可以和圖演算法類似:
[cpp]view plain
copy
#include
#include
using
namespace
std;
const
intmaxn=110;
intn, q;
intu, v, w;
intdp[maxn][maxn];
struct
node
; vectoradj[maxn];
void
init( )
} void
dfs(
introot,
intfather,
intleft)
} } }
if(left==1)
return
; }
intmain( )
return
0;
}
樹形動態規劃
description 有一棵蘋果樹,如果樹枝有分叉,一定是分2叉 就是說沒有只有1個兒子的結點 這棵樹共有n個結點 葉子點或者樹枝分叉點 編號為1 n,樹根編號一定是1。我們用一根樹枝兩端連線的結點的編號來描述一根樹枝的位置。下面是一顆有4個樹枝的樹 2 5 3 4 1現在這顆樹枝條太多了,需要剪...
樹形動態規劃
問題可以分解成若干相互聯絡的階段,在每乙個階段都要做出決策,全部過程的決策是乙個決策序列。要使整個活動的總體效果達到最優的問題,稱為多階段決策問題。動態規劃就是解決多階段決策最優化問題的一種思想方法。將所給問題的過程,按時間或空間特徵分解成若干相互聯絡的階段,以便按次序去求每階段的解 各階段開始時的...
選課 樹形動態規劃
題目大意 在大學裡每個學生,為了達到一定的學分,必須從很多課程裡選擇一些課程來學習,在課程裡有些課程必須在某些課程之前學習,如高等數學總是在其它課程之前學習。現在有n門功課,每門課有個學分,每門課有一門或沒有直接先修課 若課程a是課程b的先修課即只有學完了課程a,才能學習課程b 乙個學生要從這些課程...