貪心演算法求解背包問題

来源: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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...