明顯是樹上揹包問題,選與不選,保留的樹枝為體積,每個樹枝的蘋果樹目為價值
f [ i ] [ j ] 表示在 i 節點時,留下了 j 條樹枝時得到的最多蘋果數量
模板列舉孩子節點
·····搜尋更新孩子節點資訊
·····列舉 i 點樹枝數量
············列舉孩子節點所擁有樹枝數量
··················狀態轉移方程
狀態轉移方程:
f [ u ] [ j ] = max ( f [ u ] [ j ] , f [ u ] [ j - k ] + f [ v ] [ k ] )
記得初始化
#include
using
namespace std;
struct edge
e[105];
int fa[
105]
,n,m,cnt,head[
105]
,f[105][
3000050];
void
add(
int u,
int v)
void
dfs(
int u)
}int
main()
for(
int i=
1;i<=n;i++)if
(!fa[i]
)return0;
}
更上題差不多,樹形揹包板子題,要注意當我們規定所有樹的根統一為0,所選總科目應該為m+1,0節點的科目沒有的分,所以不影響答案
#include
using
namespace std;
struct edge
e[305];
int cnt,f[
305]
[6005
],head[
305]
,n,m;
intread()
while
(isdigit
(ch)
)return x*f;
}void
add(
int u,
int v)
void
dfs(
int u)
}int
main()
dfs(0)
;//約定以0為根進行樹上dp
printf
("%d"
,f[0
][m+1]
);return0;
}
類似的樹形揹包
f [ i ] [ j ] 表示在 i 節點擊擇 j 個人時的最大利潤
初始化:葉子節點 f [ i ] [ 1 ] = val [ i ]
接著就是純真無邪的樹上揹包了。
結果t4個點,對於這個題,我們可以:
!!!減掉無用轉移!!!
對於每個節點,它並不是能夠選取到所有的人(因為它子樹的葉子節點並不一定會包括所有的葉子節點),所以說我們在搜尋所有的子樹時,都應該返回該子樹所包含的葉子節點,然後對 j 進行優化列舉,減少轉移次數,然後ac
#include
#define rg register
using
namespace std;
const
int minn=
-1e7
;struct edge
e[10105];
int cnt,n,m,val[
3005
],f[
3005][
3005
],head[
3005];
inline
intread()
while
(isdigit
(ch)
)return x*f;
}inline
void
add(
int u,
int v,
int w)
inline
intdfs
(int u)
}return sum+
(val[u]?1
:0);
}int
main()
}for
(rg int i=
1;i<=n;i++
)for
(rg int j=
1;j<=m;j++
) f[i]
[j]=minn;
for(rg int i=n-m+
1;i<=n;i++
) f[i][1
]=val[i]
=read()
;dfs(1
);int l=
1,r=m;
while
(l<=r)
//小優化
if(f[1]
[r]>=0)
printf
("%d"
,r);
else
printf
("%d",0
);return0;
}
記得補
#include
using
namespace std;
const
int inf=
1e8;
struct edge
e[160];
int n,p,cnt,root;
int f[
155]
[155
],head[
155]
,a[155];
bool bj[
155]
;void
add(
int u,
int v)
intdp
(int x)
return sum;
}int
main()
memset
(f,0x3f
,sizeof
(f))
;for
(int i=
1;i<=n;i++)dp
(root)
;int ans=f[root]
[p];
for(
int i=
1;i<=n;i++)if
(f[i]
[p][p]+1;
printf
("%d"
,ans)
;return0;
}
題目的意思是,小偷要從外面進到美術館,偷完東西後再出美術館,所以一條邊坑定是要走兩次的(來回),而警察來了的時候就判定為被抓到,所以當小偷剛好花費 s 時間時,並不能作為最優答案輸出(坑)
這一道題主要是建邊,以遞迴的形式建邊,根節點為1,因為題目性質,所以乙個點度數只為0或2,保證了該美術館就是乙個二叉樹,
然後就可以按照題目的意思來儲存樹
樹的左孩子為 i < < 1,右孩子為 i < < 1 | 1
所以接下來dp的時候就應該從1出發
f [ i ] [ j ] 表示在 i 節點剩餘 j 分鐘 能偷到的畫的最大數量
注意事項:
s–存邊時直接將邊長<<1(來回走)
dp邊界,當沒有時間或者 節點i 所剩時間j已經被更新過時,可以直接結束dp
dp特判:如果該節點有畫,那麼就花所剩餘的時間偷畫(在i節點偷到畫的數量一定小於等於該節點畫的數量)
dp轉移方程:
列舉i點左子樹所剩餘的時間 j
(為保證能逃出去,j < = time - edge [ i ] )
f [ i ] [ j ] = max ( f [ i ] [ j ] , f [ i <<1] [ j ] , f [ i<<1|1 ] [ time - edge [ i ] - j ](應為要給自己逃跑的時間,所以右子樹所給的時間要再減去這條道路的時間)
#include
using
namespace std;
//第i個展室,共花j分鐘,
int s,f[
1005][
6005
],w[
1005
],edge[
1005];
bool bj[
1005];
void
dfs(
int u)
}intdp(
int u,
int time)
return f[u]
[time];}
intmain()
洛谷2014 選課(樹形DP 樹形揹包問題
在大學裡每個學生,為了達到一定的學分,必須從很多課程裡選擇一些課程來學習,在課程裡有些課程必須在某些課程之前學習,如高等數學總是在其它課程之前學習。現在有n門功課,每門課有個學分,每門課有一門或沒有直接先修課 若課程a是課程b的先修課即只有學完了課程a,才能學習課程b 乙個學生要從這些課程裡選擇m門...
洛谷luogu P3360 偷天換日(樹形DP)
給乙個有根樹,有邊權,葉子節點有畫可以偷,偷畫和經過邊需要時間,給定n時間,最多可以偷多少價值的畫。這奇怪的資料格式真是給跪了,葉子節點可以揹包,非葉子節點怎麼辦呢?暴力列舉!include include include include include include include define...
洛谷P2014 選課 樹形dp
給出n 300 n leq300 n 30 0個結點,每個結點都有乙個權值,然後一些結點必須只有選了前驅結點這個結點才可以被選。現在最多選m 300 m leq300 m 30 0個結點,求最大權值。實際上這個是乙個森林,但是通過設定乙個權值為0 00的虛點0 00,把所有的沒有前驅的點全部連到這個...