對於集合,相信大家都不陌生。
對於集合中的每個元素,如果我們賦予它乙個數值,這個數值就代表它的權重。假設乙個菜市場是乙個集合,那個我們可以認為,青菜、蘿蔔、豬肉、魚是這個集合的元素,這個集合記作s=;現在我們給這個集合中的每個元素標上**,青菜:1元一斤,蘿蔔:兩元一斤,豬肉:13元一斤,魚:10元一斤,那麼,我們可以認為這些元素的**就是它們的權重,這就是權重的意義。那什麼是最大加權集呢?假設現在我們去菜市場,需要購買一種蔬菜和一種葷菜。毫無疑問,在這個集合中,我們有四種選擇,分別是:青菜豬肉,青菜魚,蘿蔔豬肉,蘿蔔魚,可以很容易看出其中最貴的是蘿蔔豬肉。這裡的就是這個集合對於一葷一素的最大加權集。
很顯然的是,當我們的集合中的元素很大時,求集合的最大加權集問題是np-難的。在這裡,我們討論的就是求乙個集合最大加權集的思路。
對於以上的集合,我們可以一眼就看出它的最大加權集,然而對於我們的計算機,它的計算過程並非如此簡單,它需要把乙個個的可能性都列出來,然後進行比較,最後才能得出最大。當集合足夠的,人一眼都看不出答案時,對計算機也是一種考驗,所以需要對計算機的演算法進行優化。
我們以以上的集合為列,第一步,我們將要構建乙個衝突圖,何為衝突?何為衝突圖?在我們要買一葷一素的前提下,青菜和蘿蔔即是衝突的,豬肉和魚也是衝突的。所謂衝突圖,就上將他們的衝突關係表現在乙個二維圖示上,用1表示衝突,0表示不衝突,如下:
演算法是這樣的:設opt(u)表示u的最大加權集,val(u)表示u中所有元素的權重和
opt(s)=
val()>val(opt(s-青菜))?:(s-青菜)
(此表示式為c語言中的表示式)
此時(
s-所有與青菜衝突的元素(包括本身)) =
(s-青菜) =
以此遞迴下去,直到集合為空集。
opt() = val()>val()?:--至此集合為空,返回豬肉
opt = val(})> val(opt)?} : opt
opt() = val()
>
val() ?
: --至此集合為空,返回豬肉
此時遞迴一層層返回:
①豬肉 > 魚 return 豬肉;
②蘿蔔,豬肉 > 豬肉 return 蘿蔔,豬肉;
③青菜,豬肉 > 蘿蔔,豬肉 return 青菜,豬肉;
這是顯而易見的。
以此演算法,當集合中元素的數量很客觀時,能很好地計算出最大加權集,其**如下:
在此演算法中,我沒有計算其時間複雜性和空間複雜性,不過應該是很客觀的,有興趣的朋友可以試著算算。
關於加權的LIS問題
蒟蒻zigzag正在準備聯賽.這個算是這幾天做的唯一乙個值得寫一寫的題吧。首先lis的n 2暴力dp應該都會寫,就是f i max 1 那麼加權的就吧後面的1換成數的權值就行了,如果優先長度的話加一些判斷就行了。那麼o nlogn 怎麼寫?lis的nlogn應該都會寫,就是記乙個陣列d i 表示長度...
關於求解p x mod q的問題
如題,其中p和q都是素數,而x是數值十分大的合數,則p x mod q的一種解法可為 第一步,可把x寫成a b的形式,即p x p a b,其中p a是可以通過簡單的人為計算得出的並且滿足p a q,設c p a,則p x通過降次得到c b 第二步,把c展開,寫成c dq e的形式,則c b dq ...
最大子串行和問題的求解
問題描述 給定 可能存在負值 整數a1,a 2.a n,求最大子串行和。如果所有的整數均為負數,則最大子串行和為0.列如 對於輸入 2,11,4,13,5,2,該輸入的最大子串行和為20 11 4 13 現在我們將敘述四個演算法來求解最大子串行和問題。1.該演算法是使用窮舉法來嘗試所有的可能 演算法...