樹形DP 選課

樹上的背包問題

學(xué)校實(shí)行學(xué)分制乒融。每門的必修課都有固定的學(xué)分详民,同時(shí)還必須獲得相應(yīng)的選修課程學(xué)分。學(xué)校開設(shè)了N(N<300)門的選修課程逞带,每個(gè)學(xué)生可選課程的數(shù)量M是給定的。學(xué)生選修了這M門課并考核通過就能獲得相應(yīng)的學(xué)分纱新。


在選修課程中展氓,有些課程可以直接選修,有些課程需要一定的基礎(chǔ)知識(shí)脸爱,必須在選了其它的一些課程的基礎(chǔ)上才能選修遇汞。例如《Frontpage》必須在選修了《Windows操作基礎(chǔ)》之后才能選修。我們稱《Windows操作基礎(chǔ)》是《Frontpage》的先修課。每門課的直接先修課最多只有一門空入。兩門課也可能存在相同的先修課络它。每門課都有一個(gè)課號(hào),依次為1歪赢,2化戳,3,…埋凯。 例如:

輸入描述 Input Description

輸入文件的第一行包括兩個(gè)整數(shù)N点楼、M(中間用一個(gè)空格隔開)其中1≤N≤300,1≤M≤N。
以下N行每行代表一門課白对。課號(hào)依次為1掠廓,2,…甩恼,N蟀瞧。每行有兩個(gè)數(shù)(用一個(gè)空格隔開),第一個(gè)數(shù)為這門課先修課的課號(hào)(若不存在先修課則該項(xiàng)為0)条摸,第二個(gè)數(shù)為這門課的學(xué)分黄橘。學(xué)分是不超過10的正整數(shù)。

輸出描述 Output Description

輸出文件只有一個(gè)數(shù),實(shí)際所選課程的學(xué)分總數(shù)屈溉。

樣例輸入 Sample Input

7 4
2 2
0 1
0 4
2 1
7 1
7 6
2 2
樣例輸出 Sample Output
13
【詳見圖片】
表中1是2的先修課塞关,2是3、4的先修課子巾。如果要選3帆赢,那么1和2都一定已被選修過。   你的任務(wù)是為自己確定一個(gè)選課方案线梗,使得你能得到的學(xué)分最多椰于,并且必須滿足先修課優(yōu)先的原則。假定課程之間不存在時(shí)間上的沖突仪搔。

題解部分:
這道題看了很多老哥的題解瘾婿,是老早以前寫的了,當(dāng)時(shí)沒有人寫多叉樹的寫法烤咧,實(shí)際上我感覺多叉樹的DP其實(shí)也蠻好懂的也很直接.還是說下兩種樹形DP思路 第一種是傳統(tǒng)的記憶化搜索 給以X為根節(jié)點(diǎn)的子樹分配J個(gè)資源偏陪,那么方程應(yīng)該是F[X][J]=max(f[x][j],f[x][j-k]+dp(child[i],k));特別地,對(duì)于第一個(gè)子樹你可以直接賦值 F[X][J]=當(dāng)前節(jié)點(diǎn)X的點(diǎn)權(quán)+dp(child[1],j-1);
有個(gè)特殊注意的地方是你的分配資源給那些子樹的必然是總資源-1
因?yàn)辄c(diǎn)權(quán)占一個(gè)份額(其實(shí)這個(gè)是比較不好的寫法煮嫌,因?yàn)檫@個(gè)掛了很久)然后記得j-1倒敘枚舉 保證更新狀態(tài)不會(huì)覆蓋.
第二種方法我沒試笛谦,但是可以肯定是一個(gè)非常好的方法.
直接DP(x)用頭部遞歸找到所有子節(jié)點(diǎn)狀態(tài)然后遞歸回來做狀態(tài)轉(zhuǎn)移.
想看這種寫法的同學(xué)可以去看HAOI 軟件安裝那個(gè)題的題解.清晰簡潔,邊界條件也是弱化的.
一些關(guān)于邊界的細(xì)節(jié)可以直接看代碼了解昌阿,大概就是資源為0返回0 資源為1返回節(jié)點(diǎn)權(quán)值饥脑,無子節(jié)點(diǎn)直接返回節(jié)點(diǎn)權(quán)值(在條件2基礎(chǔ)之上)

#include <iostream>
#define maxn 302
using namespace std;
int N, M;
int f[maxn][maxn];
struct tr{
    int child[maxn];
    int num;
};
tr a[maxn];
int s[maxn];
int dfs(int cur, int k)
{
//  cout<<a[cur].child[1]<<'\n';
//  cout<<cur<<' '<<k<<'\n';
    if(k==0)
    return 0;
    if(f[cur][k]>=0)
    return f[cur][k];
    if(a[cur].num==0)
    return s[cur];
    if(k==1)
    return s[cur];
    int i, j;
    for(i=1;i<=a[cur].num;i++)
    { 
        for(j=k-1;j>=1;j--)
        {
        /*  if(cur==0&&i==1)
            {
                f[cur][j+1]=dfs(a[cur].child[i],j+1);
                cout<<cur<<' '<<j+1<<' '<<f[cur][j+1]<<'\n';
            }*/
            if(i==1)
            {
                f[cur][j+1]=s[cur]+dfs(a[cur].child[i],j);
            //  cout<<cur<<' '<<j+1<<' '<<f[cur][j+1]<<'\n';
            }
            if(i!=0)
            {
            /*  if(cur==0)
                {
                    for(int v=j;v>=1;v--)
                    {
                        f[cur][j+1]=max(f[cur][j+1], dfs(a[cur].child[i],v)+f[cur][k-v]);
                        cout<<cur<<' '<<j+1<<' '<<f[cur][j+1]<<'\n';
                    }
                }*/
                for(int v=j;v>=1;v--)
                {
                //  cout<<j-v<<'\n';
                    f[cur][j+1]=max(f[cur][j+1],dfs(a[cur].child[i],v)+f[cur][j-v+1]);
            //      cout<<cur<<' '<<j+1<<' '<<f[cur][j+1]<<'\n';
                }
            }
        }
    }
    if(cur==0)
    {
        for(i=0;i<=maxn;i++)
        {
            for(j=0;j<=maxn;j++)
            {
                if(f[i][j]<0)
                f[i][j]=0;
            }
        }
        for(i=1;i<=M;i++)
        f[cur][i]=0;
        for(i=1;i<=a[cur].num;i++)
        {
            for(j=M;j>=1;j--)
            {
                for(int v=j;v>=1;v--)
                {
                    f[cur][j]=max(f[cur][j],f[a[cur].child[i]][v]+f[cur][j-v]);
                //  cout<<a[cur].child[i]<<' '<<v<<' '<<f[a[cur].child[i]][v]<<' '<<f[cur][j-v]<<'\n';
                }
            }
        }
    }
    return f[cur][k];
}
int main() {
    int i, j, k;
    cin>>N>>M;
    for(i=1;i<=N;i++)
    {
        a[i].num=0;
    }
    for(i=1;i<=N;i++)
    {
        int ta, tb;
        cin>>ta>>tb;
        a[ta].child[++a[ta].num]=i;
        s[i]=tb;
    }
/*  for(i=0;i<=N;i++)
    {
        for(j=1;j<=a[i].num;j++)
        {
            cout<<a[i].child[j]<<' ';
        }
        cout<<'\n';
    }*/
    for(i=0;i<=N;i++)
    {
        for(j=0;j<=M;j++)
        {
            if(j==0)
            f[i][j]=0;
            if(j==1)
            f[i][j]=s[i];
            else
            f[i][j]=-1;
        }
    }
    cout<<dfs(0,M);
    return 0;
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末恳邀,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子灶轰,更是在濱河造成了極大的恐慌谣沸,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件笋颤,死亡現(xiàn)場離奇詭異乳附,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)椰弊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門许溅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人秉版,你說我怎么就攤上這事贤重。” “怎么了清焕?”我有些...
    開封第一講書人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵并蝗,是天一觀的道長。 經(jīng)常有香客問我秸妥,道長滚停,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任粥惧,我火速辦了婚禮键畴,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘突雪。我一直安慰自己起惕,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開白布咏删。 她就那樣靜靜地躺著惹想,像睡著了一般。 火紅的嫁衣襯著肌膚如雪督函。 梳的紋絲不亂的頭發(fā)上嘀粱,一...
    開封第一講書人閱讀 51,443評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音辰狡,去河邊找鬼锋叨。 笑死,一個(gè)胖子當(dāng)著我的面吹牛搓译,可吹牛的內(nèi)容都是我干的悲柱。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼些己,長吁一口氣:“原來是場噩夢啊……” “哼豌鸡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起段标,我...
    開封第一講書人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤涯冠,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后逼庞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蛇更,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年赛糟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了派任。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡璧南,死狀恐怖掌逛,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情司倚,我是刑警寧澤豆混,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站动知,受9級(jí)特大地震影響皿伺,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜盒粮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一鸵鸥、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧丹皱,春花似錦妒穴、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至爽室,卻和暖如春汁讼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背阔墩。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來泰國打工嘿架, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人啸箫。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓耸彪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親忘苛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蝉娜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 樹形動(dòng)態(tài)規(guī)劃唱较,顧名思義就是樹+DP,先分別回顧一下基本內(nèi)容吧:動(dòng)態(tài)規(guī)劃:問題可以分解成若干相互聯(lián)系的階段召川,在每一個(gè)...
    Mr_chong閱讀 1,486評(píng)論 0 2
  • 背景 一年多以前我在知乎上答了有關(guān)LeetCode的問題, 分享了一些自己做題目的經(jīng)驗(yàn)南缓。 張土汪:刷leetcod...
    土汪閱讀 12,744評(píng)論 0 33
  • 一年級(jí)語文上冊生字表 生字表一(共400字) 啊(ā)愛(ài)安(ān)岸(àn)爸(bà)八(bā)巴(bā)...
    meychang閱讀 2,796評(píng)論 0 6
  • 想法太多,顧慮太多荧呐,讓自己無法前進(jìn)汉形。仔細(xì)想想,是自己困住了自己倍阐,是自己給自己戴上了枷鎖概疆。
    Iris_思琪閱讀 62評(píng)論 0 0
  • 在無所謂掙扎與所向披靡中等待死亡
    沐歌1010閱讀 174評(píng)論 0 0