1. 程式人生 > >金明的預算方案加選課(樹上的揹包)

金明的預算方案加選課(樹上的揹包)

【模擬試題】選課

Time Limit:10000MS  Memory Limit:65536K
Total Submit:365 Accepted:166 
Case Time Limit:1000MS

Description

   在大學裡每個學生,為了達到一定的學分,必須從很多課程裡選擇一些課程來學習,在課程裡有些課程必須在某些課程之前學習,如高等數學總是在其它課程之前 學習。現在有N門功課,每門課有個學分,每門課有一門或沒有直接先修課(若課程a是課程b的先修課即只有學完了課程a,才能學習課程b)。一個學生要從這 些課程裡選擇M門課程學習,問他能獲得的最大學分是多少?

Input

  第一行有兩個整數N,M

用空格隔開。(1<=N<=300,1<=M<=200) 
  接下來的N,I+1行包含兩個整數kisi, ki表示第I門課的直接先修課,si表示第I門課的學分。若ki=0表示沒有直接先修課(1<=ki<=N, 1<=si<=20)。

Output

  只有一行,選M門課程的最大得分。

Sample Input

  7 4

  2 2

  0 1

  0 4

  2 1

  7 1

  7 6

  2 2

Sample Output

  13

Source

xinyue

題意:你要在n門課中選出m門,使得獲得的學分最大,當然有的課依賴於別的課先選。。。

分析:很容易想到在樹上揹包來解決問題,假設f[i][j]為以i為根的子樹,包括i,選擇j門課的最大值

那麼有f[i][j]=max{ f[i][a]+f[k][b] }k是i的子樹,a+b=j

這樣的複雜度是O(n*m^2)對於這題的資料範圍來說還是夠用的,不過我用上了對這種泛化物品的揹包的一種優化

複雜度降為O(n*m)

【AC程式碼】

#include <bits/stdc++.h>
using namespace std;
const int maxn = 302;
int dp[maxn][maxn],k[maxn],s[maxn];
int n,m;
void Tree_dp(int root,int c)
{
    if(c){
        for(int i=1; i<=n; i++){
            if(k[i]==root){
                for(int j=0; j<c; j++)//最多選j門課
                    dp[i][j] = dp[root][j] + s[i];
                Tree_dp(i,c-1);
                for(int j=1; j<=c; j++){
                    dp[root][j] = max(dp[root][j],dp[i][j-1]);
                }
            }
        }
    }
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1; i<=n; i++)scanf("%d%d",&k[i],&s[i]);
        //init.
        for(int i=1; i<=m; i++) dp[0][i] = 0;
        Tree_dp(0,m);
        printf("%d\n",dp[0][m]);
    }
    return 0;
}

【金明的預算方案】

和上題一樣,同屬於有依賴性的揹包問題,這裡才用樹形dp+泛化物品的方法解決這個問題!

#include <bits/stdc++.h>
using namespace std;
const int maxn = 32002;
int dp[62][maxn],v[maxn],p[maxn],q[maxn];
int n,m;
void Tree_dfs(int root,int c)
{
    if(c)
    {
        for(int i=1; i<=n; i++){
            if(q[i]==root){
                for(int j=0; j<=c-v[i]; j++){
                    dp[i][j] = dp[root][j] + p[i]*v[i];
                }
                Tree_dfs(i,c-v[i]);
                for(int j=v[i]; j<=c; j++){
                    dp[root][j] = max(dp[root][j],dp[i][j-v[i]]);
                }
            }
            else
                continue;
        }
    }
}
int main()
{
    while(~scanf("%d%d",&m,&n))
    {
        for(int i=1; i<=n; i++) scanf("%d%d%d",&v[i],&p[i],&q[i]);
        for(int i=1; i<=m; i++) dp[0][i] = 0;
        Tree_dfs(0,m);
        printf("%d\n",dp[0][m]);
    }
    return 0;
}


相關推薦

預算方案選課樹上揹包

【模擬試題】選課 Time Limit:10000MS  Memory Limit:65536K Total Submit:365 Accepted:166  Case Time Limit:1000MS Description    在大學裡每個學生,為了達到一定的

【洛谷1273】有線電視網樹上揹包

點此看題面 大致題意: 給你一棵帶權樹,已知每連線一條邊需要一定花費,如果某個葉節點能到達根,可以獲得一定收益。問在不虧本的情況下,最多能使多少個葉節點能到達根。 樹上揹包 這是一道比較經典的樹上揹包

hdu1561、The more, The Better樹上揹包

The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 9999    Acc

51nod_1490: 多重遊戲樹上博弈

== names lin its code bit 都是 namespace 51nod 題目鏈接 該題實質上是一個樹上博弈的問題。要定義四種狀態——2先手必勝 1先手必敗 3可輸可贏 0不能控制 葉子結點為先手必勝態; 若某結點的所有兒子都是先手必敗態,則該結點為先手必

光貓手機自動激活系統-開發指南-004- OLT添vlanADD- VLAN

手機 光貓 手機激活系統 -開發指南-004- olt添加vlan(add- vlan) ADD-VLAN::OLTID=10.124.202.199:CTAG::VLAN=2108,DESC=2108,VLANMODE=SINGLE,PORTLIST=NA-0-19-0|NA-0-20-0|

ARC078 D.Fennec VS. Snuke樹上博弈

turn 路徑 std oid 最大 main 沒有 次數 cto 題目大意: 給定一棵n個結點的樹 一開始黑方占據1號結點,白方占據n號結點 其他結點都沒有顏色 每次黑方可以選擇黑色結點臨近的未染色結點,染成黑色 白方同理。 最後誰不能走誰輸。 題解: 其實簡單想想就

Redis的集群方案之Sentinel哨兵模式待實踐

tps log csdn mooc 實現 tail net sentinel .net 哨兵模式是主從切換的一種方案,但是可以借助此方案實現集群,達到高可用。 先收集教程,待實踐。 參考: https://redis.io/topics/sentinel(官方文

vue和mintui-Loadmore結合實現下拉刷新,上拉待優化

res 延遲 設置 body 轉換 ext over 開發 體驗 mintui是餓了麽團隊針對vue開發的移動端組件庫,方便實現移動端的一些功能,這裏只用了Loadmore功能實現移動端的上拉分頁刷新,下拉加載數據.mintui官網:http://mint-ui.githu

vue組件重新刷新

自己 組件 vue組件 自己的 AI exp vue ace div vue組件重新加載(刷新) 第一種方法:利用v-if控制router-view,在根組件APP.vue中實現一個刷新方法 <template> <router-view v-i

hdu6223 Infinite Fraction Path 2017沈陽區域賽G題 bfs剪枝好題

getc 細節 \n ret ast scrip mat tom ide 題目傳送門 題目大意:給出n座城市,每個城市都有一個0到9的val,城市的編號是從0到n-1,從i位置出發,只能走到(i*i+1)%n這個位置,從任意起點開始,每走一步都會得到一個數字,走n-1步,會

ceph添osdceph-deploy

配置文件 秘鑰 之一 alt udev dep 修改主機名 ceph host 修改主機名和 /etc/hosts 關閉防火墻和 SELINUX 安裝和配置 NTP ceph-deploy 節點安裝 安裝 ceph-deploy sudo yum install ceph-

PAT-乙-1074 1074 宇宙無敵法器 20 分

程式碼 #include <iostream> using namespace std; int main() { string s, s1, s2; cin>>s>>s1>>s2; while(s1.length()

洛谷-P2014 選課樹形DP

題意 n n n 門功課形成一棵樹,每門課有一個學分,選 m m m 門,選擇一門課的前提是選擇它的父親,求最大學分。

FJUT 聰明的商人樹上倍增題解

思路:求樹上兩點的距離,顯然是dep[u] + dep[v] - 2 * dep[lca],用樹上倍增去寫。 參考:樹上倍增的寫法和應用(詳細講解,新手秒懂) 程式碼: #include<set> #include<map> #include<stack> #i

BZOJ4753: [Jsoi2016]最佳團體分數規劃+樹上揹包

BZOJ4753: [Jsoi2016]最佳團體(分數規劃+樹上揹包) 標籤:題解 閱讀體驗 BZOJ題目連結 洛谷題目連結 具體實現 看到分數和最值,考慮分數規劃 我們要求的是一個\(\dfrac{\sum P_i}{\sum S_i}\)最大對吧,考慮二分一個答案\(mid\) 那麼就會有合法條件\

[LeetCode]66. Plus OneJava

一、題目: LeetCode地址 給定一個由整數組成的非空陣列所表示的非負整數,在該數的基礎上加一。 最高位數字存放在陣列的首位, 陣列中每個元素只儲存一個數字。 你可以假設除了整數 0 之外,這個整數不會以零開頭。 示例 1: 輸入: [1,2,3] 輸出:

給影象噪聲椒鹽噪聲

原理:隨機的將影象某些畫素值改為0或255 新增椒鹽噪聲 def SaltAndPepper(src,percetage): SP_NoiseImg=src SP_NoiseNum=int(percetage*src.shape[0]*src.shape[1]) for i

牛客網 272B Xor Path樹上操作

題目連結:Xor Path 題意:每個頂點的點權為Ai,任意兩點路徑上點權異或和為Path(i,j),求所有Path(i,j)和。 題解:考慮每個頂點被用到的次數,分以下三種情況: 1.本身和其他頂點:n-1 2.該頂點上面的頂點(k)和下面的頂點(m)通過該點進行連線:k*m 3.該頂底下面的頂點

PAT乙級 1074 宇宙無敵法器 20 分

地球人習慣使用十進位制數,並且預設一個數字的每一位都是十進位制的。而在 PAT 星人開掛的世界裡,每個數字的每一位都是不同進位制的,這種神奇的數字稱為“PAT數”。每個 PAT 星人都必須熟記各位數字的進製表,例如“……0527”就表示最低位是 7 進位制數、第 2 位是 2 進位制數、第

【Android】_UI設計_學生註冊、選課無資料庫

學生管理系統 (一) 效果實現圖 (二) 專案結構圖 (三) 具體的編碼實現 (1)註冊 (2)註冊 (3)配置檔案 (一) 效果實現圖 目標:通過一個SQLite的資料庫的操作實現學