現在我們的手頭有n個軟體,對於乙個軟體i,它要占用wi的磁碟空間,它的價值為vi。我們希望從中選擇一些軟體安裝到一台磁碟容量為m計算機上,使得這些軟體的價值盡可能大(即vi的和最大)。
但是現在有個問題:軟體之間存在依賴關係,即軟體i只有在安裝了軟體j(包括軟體j的直接或間接依賴)的情況下才能正確工作(軟體i依賴軟體j)。幸運的是,乙個軟體最多依賴另外乙個軟體。如果乙個軟體不能正常工作,那麼它能夠發揮的作用為0。
我們現在知道了軟體之間的依賴關係:軟體i依賴軟體di。現在請你設計出一種方案,安裝價值盡量大的軟體。乙個軟體只能被安裝一次,如果乙個軟體沒有依賴則di=0,這時只要這個軟體安裝了,它就能正常工作。
輸入格式:
第1行:n, m (0<=n<=100, 0<=m<=500)
第2行:w1, w2, ... wi, ..., wn (0<=wi<=m )
第3行:v1, v2, ..., vi, ..., vn (0<=vi<=1000 )
第4行:d1, d2, ..., di, ..., dn (0<=di<=n, di≠i )
輸出格式:
乙個整數,代表最大價值
輸入樣例#1:
3 10
5 5 6
2 3 4
0 1 1
輸出樣例#1:
5
演算法:
樹形dp
分析:
一看到這道題,就感覺和選課很相似,不過再仔細一看,就發現其實之間大有不同。
選課一題,是不可以成環的,因為先修課的先修課不可能成為後面的後修課,所以,判環是沒必要的。
但是這道題,非常坑爹,它可以出現環。若出現a依賴b,b依賴c,c依賴a,那麼我們究竟怎麼搜尋呢,而且轉移方程也不好寫。
我們通過觀察發現,這種環狀的問題,要是選了其中乙個,那麼就意味著要把整個環給選了,要麼不選,就得整個都不選。
所以,我們就可以從這裡入手,把乙個個的環縮成乙個個新的點,乙個點代表了環的整體。
接下來就可以通過選課的後續思路,建造一棵左兒子右兄弟的二叉樹,通過多叉樹轉二叉樹進行記憶化搜尋。
後面的就很簡單了,狀態轉移方程就是要不要當前的兄弟,還是把機會分給兄弟和孩子。
不過中途有很多小點需要注意。
判環要用floyed的方法三重for來判斷環,記得三個迴圈的變數順序不能錯,否則後果會判不到環。
其次,縮點建點的時候,主體分三個情況來判斷:
1、這是新環,我需要建點來記錄,他的價值和體積我都直接相加就好了。不過我們要記得把已經轉移的新點的原來兩個舊點序號變成負數,而新點的下標+舊點的內容恰好是等於n的,每乙個環一一對應,不多也不會少,詳情見**操作。
2、這是舊環,我發現了新的點,這個點在環內。那麼我就把這個點並到環中,把價值和體積也加到新點上,然後把原來這個舊環的密碼推到這個新點上。
3、找到乙個新點,他和乙個舊環有聯絡,但不屬於這個環的一部分,於是把它的從屬關係推到新的點上。
步驟簡化為:判環+縮點+多叉轉二叉+記憶化搜尋。
上**:
1 #include2 #include3 #include4using
namespace
std;56
const
int size=600;7
int n,m,ans,sum,d[size],v[size],w[size],f[size][4*size],b[size],c[size];
8bool a[size][size]; //
是否連通
910 inline int read() //
讀入優化
1120
21void floyed() //
floyd判環
2230
31void connect() //
縮點建點
3246
else
47if (w[d[j]]<0&&w[j]>0) //
發現舊環
4855
else
//不屬於環
56if (a[d[j]][j]&&!a[j][d[j]]||!a[d[j]][j]&&a[j][d[j]])
57 d[j]=n-w[d[j]];58}
59}60}
6162
int dfs(int root,int val) //
記憶化搜尋
6377
return
f[root][val];78}
7980
intmain()
8194
floyed();
95connect();
96for (i=1;i<=ans;i++) //
模擬鍊錶
97if (w[i]>0)98
102 printf("
%d",dfs(c[0
],m));
103return0;
104 }
這道題其實難度很大,不過只要把原理弄懂,**還是很好打的,主要就是圍繞著如何更加簡便地進行記憶化搜尋,然後一層層地進行優化,這道題用到的就是判環和縮點的知識。
嗯,就這樣了。
洛谷 P2515 HAOI2010 軟體安裝
現在我們的手頭有n個軟體,對於乙個軟體i,它要占用wi的磁碟空間,它的價值為vi。我們希望從中選擇一些軟體安裝到一台磁碟容量為m計算機上,使得這些軟體的價值盡可能大 即vi的和最大 但是現在有個問題 軟體之間存在依賴關係,即軟體i只有在安裝了軟體j 包括軟體j的直接或間接依賴 的情況下才能正確工作 ...
P2515 HAOI2010 軟體安裝
傻了。思路 scc 縮點,樹上揹包。提交 2次 無語。建邊建錯了 思路 關係可能會形成環,而整個環是乙個整體 要選就選環上所有點,否則整個不選 所以我們先把所有的環縮點,然後便形成了一棵樹 乙個點不可能有兩個父親 然後跑樹上揹包。include include using namespace std...
P2515 HAOI2010 軟體安裝
現在我們的手頭有n個軟體,對於乙個軟體i,它要占用wi的磁碟空間,它的價值為vi。我們希望從中選擇一些軟體安裝到一台磁碟容量為m計算機上,使得這些軟體的價值盡可能大 即vi的和最大 但是現在有個問題 軟體之間存在依賴關係,即軟體i只有在安裝了軟體j 包括軟體j的直接或間接依賴 的情況下才能正確工作 ...