題意:給m門課,每門課在上完其先修課後才能上,要你從中選n門課使得總學分盡可能大。
思路:揹包,沒有先修課看成其先修課編號為0,求乙個f[0][n]的揹包,表示以0為根的樹選n個結點的最大總權值,設x為根,y為x的孩子,對每個孩子,dfs(y),然後f[[x][t]=max(f[x][t],f[x][t-j]+f[y][j])用每個孩子更新x,最後若x不是0,再用自己的權值更新自己。但揹包好像不能記錄路徑。
1 #include2view code#define rep(i,a,b) for(int i=a;i<=b;++i)
3#define dep(i,a,b) for(int i=a;i>=b;--i)
4using
namespace
std;
5const
int maxn=310;6
intread()
13int
n,m;
14int
v[maxn];
15 vectorson[maxn];
16int
f[maxn][maxn];
17void
init()24}
25void dp(int
x)35
if(x!=0) dep(t,m,1) f[x][t]=f[x][t-1]+v[x];36}
37int
main()
多叉轉二叉,左孩子右兄弟。
若選根結點,f[i][j] = f[br[i][j]
若不選根結點,f[i][j] = f[ch[i]][k]+f[br[i]][j-1-k]+v[i]
遞迴尋找路徑方法類似。
1 #include2view code#define rep(i,a,b) for(int i=a;i<=b;++i)
3#define dep(i,a,b) for(int i=a;i>=b;--i)
4using
namespace
std;
5const
int maxn=510;6
intread()
13int
n,m;
14int
v[maxn];
15int
br[maxn],ch[maxn];
16bool
ans[maxn];
17int
f[maxn][maxn];
18void
init()
28 memset(f,-1,sizeof
f);29}30
void dp(int x,int
y)33
dp(br[x],y);
34 rep(i,0,y-1)39
}40void path(int x,int
y)51}52
}53}54
intmain()
(選課)揹包類樹形dp
選課 學校實行學分制。每門的必修課都有固定的學分,同時還必須獲得相應的選修課程學分。學校開設了 n 門的選修課程,每個學生可選課程的數量 m 是給定的。學生選修了這 m 門課並考核通過就能獲得相應的學分。在選修課程中,有些課程可以直接選修,有些課程需要一定的基礎知識,必須在選了其他的一些課程的基礎上...
選課(樹形DP)
在大學裡每個學生,為了達到一定的學分,必須從很多課程裡選擇一些課程來學習,在課程裡有些課程必須在某些課程之前學習,如高等數學總是在其它課程之前學習。現在有n門功課,每門課有個學分,每門課有一門或沒有直接先修課 若課程a是課程b的先修課即只有學完了課程a,才能學習課程b 乙個學生要從這些課程裡選擇m門...
樹形dp 選課
題目描述 description 學校實行學分制。每門的必修課都有固定的學分,同時還必須獲得相應的選修課程學分。學校開設了n n 300 門的選修課程,每個學生可選課程的數量m是給定的。學生選修了這m門課並考核通過就能獲得相應的學分。在選修課程中,有些課程可以直接選修,有些課程需要一定的基礎知識,必...