日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

背包类树形DP 选课题解

發布時間:2024/4/17 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 背包类树形DP 选课题解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目傳送門;

我覺得題目給出0節點作為虛擬課程,也避免了我們要去想將若干個森林建成一棵樹;將N個節點的森林建成了N+1條邊的樹;

其次,我們對這個題進行一個分析;

很容易想到F【x,t】表示以x為根的子樹中,選擇t門課程所獲得得最高學分;

在x的子樹中選擇節點y,再以y為根的子樹中,選擇c_i門課程,保證Σc_i = t - 1;

初始狀態,t=0時,F【x,t】=0;

通過分析狀態轉移方程,該方程實際上是一個分組背包模型,第i組的第j個物品體積為j,價值為F[y,j],背包總容積t-1;

我們要從每組中選擇不超過1個物品(每個子節點y都只能選擇一個狀態轉移到x),在選擇總物品不超過t-1的前提下,學分最大;

是背包與樹形DP的結合;

?

#include<bits/stdc++.h> using namespace std; int lin[1000],tot,n,m,x,f[400][400],s[400]; template<typename T>inline void read(T &x) {x=0;T f=1,ch=getchar();while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getchar();}while(isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}x*=f; } struct gg {int y,next; }a[2000]; inline void add(int x,int y) {a[++tot].y=y;a[tot].next=lin[x];lin[x]=tot; } inline void dp(int x) {f[x][0]=0;for(int i=lin[x];i;i=a[i].next) {int y=a[i].y;dp(y);//倒序循環當前選課總門數,或者背包的總體積; for(int t=m;t>=0;--t) {//循環更深子樹上的選課門數(組內物品);//此處倒序是為了正確處理組內體積為0的物品,這樣可以從初始狀態f【x,0】轉移;for(int j=t;j>=0;--j) {if(t-j>=0) {f[x][t]=max(f[x][t],f[x][t-j]+f[y][j]);}}}}if(x!=0) {//x!=0,選修x本身需要占用1節課,獲得相應的學分; for(int t=m;t>0;t--) f[x][t]=f[x][t-1]+s[x];} } int main() {read(n);read(m);for(int i=1;i<=n;i++) {read(x);add(x,i);read(s[i]);}dp(0);cout<<f[0][m]<<endl;return 0; }

?

轉載于:https://www.cnblogs.com/Tyouchie/p/10830072.html

總結

以上是生活随笔為你收集整理的背包类树形DP 选课题解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。