USING INDUCTION TO DESIGN 使用歸納法設計演算法 [11/14]

來源:互聯網
上載者:User

接上文:http://blog.csdn.net/jj12345jj198999/article/details/6624864

 

基本情況很簡單,如果僅有一個大小為K的物品有辦法解決。如果有解決P(n-1,K)的辦法,也就是說如果有能夠把n-1個物品放入背包的方法我們就算完成了。我們只需要簡單的不使用第n個物品即可。然而,假設沒有對P(n-1,K)的解決方案,我們能夠使用這個否定的結論嗎?答案是可以的,這也意味著第n個物品必須被包含進去。在這種情況下,剩下的物品必須裝入一個更小的容量為K-kn的背包。我們把問題簡化為了兩個更小的問題:如果P(n,K)有解那麼P(n-1,K)或者P(n-1,K-kn)兩者中間必須有一個有解。為了完成這個演算法我們不僅需要求解容量為K的背包問題也需要求解對最大容量為K的所有背包的問題。(這裡存在把背包容量限制在一些減去ki後的大小之中,但是也可能不存在這樣的限制條件)

更強的歸納假設:我們已經知道對所有的0≤k≤K如何去求解P(n-1,k)。

上面的簡化並不依賴於一個特定的k值,它對所有的k值都是有效。我們可以使用這個歸納假設解決所有的0≤k≤K的P(n,k)問題。我們把P(n,k)簡化為P(n-1,k)和P(n-1,k-kn)這兩個問題。(如果k-kn<0我們就忽略第二個問題)這兩個問題都可以用歸納法求解。這是一個有效簡化我們也能找到一個演算法,但是該演算法效率不高。我們得到的僅是規模稍小一點的兩個子問題。因而在對規模的每步簡化中子問題的個數也是翻倍增長。由於對規模的簡化可能不是那麼確切,演算法可能是按照指數級增長。(根據ki的值來確定)

幸運的是,在很多情況下對這種問題提高運行效率是可行的。主要的觀察是可能的問題的總數不是很多。事實上,我們引入P(n,k)這個記號來表示該問題。對第一個參數存在n種可能性,對於第二個參數存在K種可能性。總的來說,這裡只有n*K種不同可能性的問題。在每次簡化後對問題數目翻倍會帶來指數已耗用時間,但是如果這裡只有n*K個不同的問題我們肯定對同一個問題求解了多次。如果我們記下了所有的解答我們就不需要對同一個問題求解兩次。這實際上是加強歸納假設和使用更強的歸納法(使用對所有已知的更小規模問題而不僅僅對n-1問題解答的假設)的結合。下面來看看我們如何?該方法。

我們把所有已知的結果存放在一個n×K的矩陣中。矩陣中第ij個位置包含著P(i,j)的解答資訊。使用上面更強的歸納假設後,問題簡化為基本上計算矩陣的第n行值即可。第n行的每個條目是通過其上的兩個條目計算得到的。如果我們對找到實際的集合感興趣的話,我們可以在每個位置加上一個標記欄位,該欄位可以表示在那步操作中對應的物品是否被選中。標記欄位可以從第(n,K)個位置反向推算,集合也可以被複原。這個演算法列在下一列頂部。

背包演算法{k1,k2...kn,K:整型};
{如果對於前i個元素和容量為j的背包有解那麼P[i,j].exist=true,如果第i個元素包含在解中那麼P[i,j].belong=true}
begin
 P[0,00].exist:=true;
 for j:=1 to n do
  P[0,j].exist:=false;
 for i:=1 to n do
  for j:=0 to K do
   P[i,j].exist:=false;{預設值}
   if P[i-1,j].exist then
    P[i,j].exist:=true;
    P[i,j].belong:=false;
   else if j-ki≥0 then
    P[i-1,j-ki].exist then
     P[i,j].exist:=true;
     P[i,j].belong:=true;
end;

複雜度:矩陣中有n×K個條目,從兩個不同條目計算出一個條目需要常數時間。因此,總的已耗用時間是O(nK)。如果物品的大小不是特別大,那麼K就不可能太大並且nK比n的指數表示要小很多。(如果K非常大或者是一個實數,那麼這種方法就不高效)如果我們只關心確定是否存在一個解答那麼答案就在P[n,K]中。如果我們對找到實際的集合感興趣,我們可以從第(n,K)個條目反向推算,例如使用背包程式中的belong標誌位,在O(n)時間內複原這個集合。 

結論:我們剛才使用的是一種常見技術方法的一個具體執行個體,該方法被稱為動態規劃,它的本質是建立一個巨大的表,在表中填入已知的之前的解答。該表是用迭代的方法進行構造的。矩陣中的每個條目都是從其上或左側的其他條目計算得到的。主要的問題是用一種最有效方法進行表的構造。動態規劃在問題僅能被簡化為幾個不是足夠小的子問題時是有效。

最大的反例【標題2】

在證明數學定理中一種有特色並且強大的技巧是假設定理的反面成立然後找到一個矛盾。通常這是用一種完成非建設性的方式實現的,這對於我們的類比不是很有用。雖然有時通過一種和歸納法類似的方法能夠找到一個矛盾。假設我們想證明一個確定的變數P(在一個給定的問題中)能夠取到一個確定的值n。第一步我們給出P能夠取到一個小值(基本情況)。第二步我們假設P無法取到n,我們可以考慮它能取到的最大值k<n。最後以及最主要的步驟是給出一個矛盾,通常針對最大化的假設。我們給出一個演算法設計的例子,在該例子中這種技術非常有用。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.