貪心演算法求解背包問題

来源:http://www.cnblogs.com/wzt-blog/archive/2017/12/06/7995233.html
-Advertisement-
Play Games

貪心演算法(又稱貪婪演算法)是指,在對問題求解時,總是做出在當前看來是最好的選擇。也就是說,不從整體最優上加以考慮,他所做出的僅是在某種意義上的局部最優解。貪心演算法不是對所有問題都能得到整體最優解,但對範圍相當廣泛的許多問題他能產生整體最優解或者是整體最優解的近似解。 ...


一.貪心演算法                                 

  1.貪心演算法概念

  貪婪演算法(Greedy algorithm)是一種對某些求最優解問題的更簡單、更迅速的設計技術。用貪婪法設計演算法的特點是一步一步地進行,常以當前情況為基礎根據某個優化測度作最優選擇,而不考慮各種可能的整體情況,它省去了為找最優解要窮盡所有可能而必須耗費的大量時間,它採用自頂向下,以迭代的方法做出相繼的貪心選擇,每做一次貪心選擇就將所求問題簡化為一個規模更小的子問題,通過每一步貪心選擇,可得到問題的一個最優解,雖然每一步上都要保證能獲得局部最優解,但由此產生的全局解有時不一定是最優的,所以貪婪法不要回溯。

  貪婪演算法是一種改進了的分級處理方法。其核心是根據題意選取一種量度標準。然後將這多個輸入排成這種量度標準所要求的順序,按這種順序一次輸入一個量。如果這個輸入和當前已構成在這種量度意義下的部分最佳解加在一起不能產生一個可行解,則不把此輸入加到這部分解中。這種能夠得到某種量度意義下最優解的分級處理方法稱為貪婪演算法。

  2.貪心演算法求解思路

  基本思路①建立數學模型來描述問題。②把求解的問題分成若幹個子問題。③對每一子問題求解,得到子問題的局部最優解。④把子問題的解局部最優解合成原來解問題的一個解。

  實現該演算法的過程:從問題的某一初始解出發;while 能朝給定總目標前進一步 do;求出可行解的一個解元素;由所有解元素組合成問題的一個可行解。

  3.利用貪婪策略,需要解決的兩個問題

 

  確定問題是否能用貪心策略求解;一般來說,適用於貪心策略求解的問題具有以下特點:貪心選擇性質和最優子結構性質。
  ① 貪心選擇性質:可通過局部的貪心選擇來達到問題的全局最優解。運用貪心策略解題,一般來說需要一步步的進行多次的貪心選擇。在經過一次貪心選擇之後,原問題將變成一個相似的,但規模更小的問題,而後的每一步都是當前看似最佳的選擇,且每一個選擇都僅做一次。
  ② 最優子結構性質:原問題的最優解包含子問題的最優解,即問題具有最優子結構的性質。在背包問題中,第一次選擇單位質量最大的貨物,它是第一個子問題的最優解,第二次選擇剩下的貨物中單位重量價值最大的貨物,同樣是第二個子問題的最優解,依次類推。

 

二.背包問題                                 

  背包問題(Knapsack problem)是一種組合優化的NP完全問題。問題可以描述為:給定一組物品,每種物品都有自己的重量和價格,在限定的總重量內,我們如何選擇,才能使得物品的總價格最高。問題的名稱來源於如何選擇最合適的物品放置於給定背包中。相似問題經常出現在商業、組合數學,計算複雜性理論、密碼學和應用數學等領域中。也可以將背包問題描述為決定性問題,即在總重量不超過W的前提下,總價值是否能達到V?它是在1978年由Merkel和Hellman提出的。

  題目有N件物品和一個容量為V的背包。第i件物品的重量是w[i],價值是v[i]。求解將哪些物品裝入背包可使這些物品的重量總和不超過背包容量,且價值總和最大。

 三.貪心演算法求解背包問題                    

 1 import java.util.Arrays;
 2 
 3 /**
 4  * 貪心演算法--->背包問題
 5  * 假設有一個背包最大可以裝    150kg 物品
 6  * 某物品    重量        價值(元)      性價比(單位重量的價格)    
 7  *   a  35kg     10              10/35
 8  *   b  30kg     40              40/30
 9  *   c  60kg     30           30/60
10  *   d  50kg     50           50/50
11  *   e  40kg     35           35/40
12  *   f  10kg     40           40/10
13  *   g  25kg     30           30/25
14  *   
15  * 求:背包可以裝入的最大價值?
16  * @author Administrator
17  *
18  */
19 public class Knapsack {
20     /**
21      * 背包最大容量
22      */
23     private static  int KNAPSACK_MAX_CAPACITY=150;
24     /**
25      * 保存各個物品的重量
26      */
27     private static int [] goods_weights=new int [] {35,30,60,50,40,10,25};
28     /**
29      * 保存各個物品的價值
30      */
31     private static int [] goods_values=new int[] {10,40,30,50,35,40,30};
32     
33     /**
34      * 貪婪演算法實現背包問題求解
35      * @param capacity  背包容量
36      * @param weights   各個物品的重量
37      * @param values    各個物品的價值
38      */
39     private void knapsackGreedy(int capacity,int weights[],int values[]) {
40         int n=weights.length;   //物品的數量
41         
42         Double[] r=new Double[n];  //保存性價比的數組
43         int [] index=new int[n]; //保存按性價比排序的物品的下標
44         //計算得到各個物品的性價比
45         for (int i = 0; i < n; i++) {
46             r[i]=(double)values[i]/weights[i];
47             index[i]=i;  //初始化各個物品的預設性價比排序
48         }
49         
50         //對各個物品的性價比進行排序
51         for(int i=0;i<r.length-1;i++) {
52             for(int j=i+1;j<r.length;j++) {
53                 if(r[i]<r[j]) {
54                     double temp=r[i];
55                     r[i]=r[j];
56                     r[j]=temp;
57                     
58                     //將排序後性價比的下標更新為性價比排序後的位置
59                     int x=index[i];
60                     index[i]=index[j];
61                     index[j]=x;
62                 }
63             }
64         }
65         
66         //將排序好的重量和價值分別保存到數組
67         int [] w1=new int[n];
68         int [] v1=new int[n];
69         for(int i=0;i<n;i++) {
70             w1[i]=weights[index[i]];
71             v1[i]=values[index[i]];
72         }
73         
74         //將物品裝入背包
75         //記錄哪些物品已經被裝入背包       0 沒有裝入背包    1 代表已經裝入背包
76         int [] x=new int[n];  
77         int maxValue=0;
78         for(int i=0;i<n;i++) {
79             if(w1[i]<=capacity) {
80                 //還可以裝的下
81                 x[i]=1;  //表示將該物品裝入背包
82                 System.out.println("物品:"+w1[i]+" 被放進了");
83                 maxValue+=v1[i];
84                 capacity-=w1[i];
85             }
86         }
87         System.out.println("總共放下的物品的數量為:"+Arrays.toString(x));
88         System.out.println("最大價值為:"+maxValue);
89     }
90     
91     
92     public static void main(String[] args) {
93         Knapsack k=new Knapsack();
94         k.knapsackGreedy(KNAPSACK_MAX_CAPACITY, goods_weights,
95                 goods_values);
96     }
97 }

 四.測試結果                               

物品:10 被放進了
物品:30 被放進了
物品:25 被放進了
物品:50 被放進了
物品:35 被放進了
總共放下的物品的數量為:[1, 1, 1, 1, 0, 0, 1]
最大價值為:170

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Observer Pattern(觀察者模式)定義: 在對象之間定義一對多的依賴,這樣一來,當一個對象改變狀態,依賴它的對象都會收到通知,並自動更新。 乾說定義肯定沒有舉例理解的透徹。想到Observer Pattern(觀察者模式)就來舉個生活中的例子來幫助我們更好消化和理解其具體含義。 舉例: ...
  • 看到這個問題,作為IT行業中的從業者,我的腦海中無數個有關產品經理的段子在策馬奔騰呼嘯而來,然鵝,基本都是黑產品的梗,那麼我們來分析一下為什麼想“打”產品經理呢?如果你是設計師、程式員、測試、美工、運營等需要和產品合作的任意一員。 ...
  • Struts 2 入門: 一:Struts 2執行流程: 1 客戶端發送請求; 2這個請求經過一系列的過濾器(Filter)(這些過濾器中有一個叫做ActionContextCleanUp的可選過濾器,這個過濾器對於Struts2和其他框架的集成很有幫助,例如:SiteMeshPlugin) 3接著 ...
  • 消息的一種開發模式,也是一種設計模式(發佈-訂閱) 中心窗體發消息(不知道消息的接受者),在中心窗體的事件中綁定的方法的對象接受消息(接受者做進一步處理)。 1.WinFrom(發佈-訂閱) 2.Windows(事件 Event) 3.Android(廣播 Broadcast) 4.Java(觀察者 ...
  • 概念 關註點分離(Separation of concerns,SOC)是對只與“特定概念、目標”(關註點)相關聯的軟體組成部分進行“標識、封裝和操縱”的能力,即標識、封裝和操縱關註點的能力。 概念 關註點分離(Separation of concerns,SOC)是對只與“特定概念、目標”(關註點 ...
  • 退出程式不用exit() #01代碼 1 #__author: _nbloser 2 #date: 2017/12/5 3 4 5 shaoguan = ['仁化', '始興', '樂昌', '南雄'] 6 jiangmeng = ['開平', '蓬江', '台山', '鶴山', '恩平'] 7 g ...
  • 21342134123 ...
  • 在上文中《Java IO(1)基礎知識——位元組與字元》瞭解到了什麼是位元組和字元,主要是為了對Java IO中有關位元組流和字元流有一個更好的瞭解。 本文所述的輸出輸出指的是Java中傳統的IO,也就是阻塞式輸入輸出(Blocking I/O, BIO),在JDK1.4之後出現了新的輸入輸出API——N ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...