貪心算法初探1—最優裝載問題以及背包問題


貪心算法算是我系統性接觸的第一個算法,在學習的過程中頁也看了一些書籍和示例,接下來介紹貪心的概念以及一個例子:

  貪心算法主要的思想是局部最優解。貪心算法在目前已有的信息上做出局部最優解,同時做出了選擇之后,不管將來有什么結果,選擇都不會有所改變,同時,貪心策略的選擇對於算法的好壞有着直接的影響。

  貪心算法的特性(滿足后可使用):

  1:貪心選擇

  指原問題的整體最優解可以通過一系列的局部最優解得出,應用同一規則,將原問題轉化為一個相似但規模更小的子問題,而后每一步都是當前最佳的選擇。這種選擇依賴於已做出的選擇。同時,貪心策略無回溯過程。

  2:最優子結構

  當一個問題的最優解包含其子問題的最優解時,稱此問題為最優子結構性質。這個性質是該問題能否用貪心解決的關鍵。

  貪心算法的使用步驟:
  1:制定貪心策略選擇一個當前看上去最好的方案(方案的選擇尤為重要)。

  2:根據貪心策略一步一步獲得局部最優解。

  3:將所有的局部最優解和成為原來問題的一個最優解。

接下來介紹兩個示例:

  1:最優裝載問題:

  問題描述:有一艘船,載重量為C,有i件古董,重量分別為Wi,如何盡可能多的裝載古董?

  解題思路:將古董重量由大到小排序,然后將其依次裝入船中,當大於船的重量時停止,最終返回轉載的數量。

  題目數據:C:30,W:4,10,7,11,3,5,14,2

  

 1  public int Solution1() {
 2         int C = 30;
 3         int[] W = new int[]{4, 10, 7, 11, 3, 5, 14, 2};
 4         Arrays.sort(W);
 5         int tmp = 0;
 6         int i = 0;
 7         while (tmp <C){
 8             tmp+=W[i];
 9             i++;
10         }
11         return i-1;
12     }//最優裝載問題解法

   最后返回值為5,時間復雜度O(n+nlogn)

  2:背包問題:

  問題描述:山中有一個山洞,洞中n種寶物,每種寶物有一定的重量W和價值V,只能運走M重量的寶物,一種拿一樣,寶物可分割,如何使寶物價值最大?

  解題思路:選擇貪心策略單位價值最大寶物,然后從性價比由高到低選擇,最終輸出寶物最大價值。

  題目數據:W:4,2,9,5,5,8,5,4,5,5;V:3,8,18,6,8,20,5,6,7,15;M:30

 1 public float Solution2(){
 2         int M=30;
 3         int[] W=new int[]{4,2,9,5,5,8,5,4,5,5};
 4         int[] V=new int[]{3,8,18,6,8,20,5,6,7,15};
 5         Item[] items=new Item[W.length];
 6         for(int i=0;i<W.length;i++){
 7             items[i]=new Item(W[i],V[i]);
 8         }//計算單位重量的價值,並將其存為一個數組
 9         Arrays.sort(items);
10         Item[] item =new Item[items.length];
11         for(int i=0;i<10;i++){
12             item[i]=items[9-i];
13         }//數組翻轉
14         float Value=0;
15         int count=0;
16         int tmp=0;//裝載的重量
17         while(tmp<M){
18             if(tmp+item[count].getW()>M || tmp+item[count].getW()==M){
19                 break;
20             }else{
21             tmp+=item[count].getW();
22             Value+=item[count].getV();
23             count++;}
24         }
25         int m=M-tmp;//剩下的重量
26         Value+=m*item[count].getV1();//拿走分割后的部分
27         return Value;
28 }
29 public class Item implements Comparable<Item>{
30     private int W;//重量
31     private int V;//價值
32     private float V1;//單位價值
33     public Item(int i1,int i2){
34         this.W=i1;
35         this.V=i2;
36         this.V1=((float) i2)/i1;
37     }
38 
39     public float getV1() {
40         return V1;
41     }
42 
43     public int getV() {
44         return V;
45     }
46 
47     public int getW() {
48         return W;
49     }
50 
51     public int compareTo(Item i){
52         if (this.V1>i.getV1()){
53             return 1;
54 
55         }else if(this.V1==i.getV1()){
56             return 0;
57         }else if(this.V1<i.getV1()){
58             return -1;
59         }
60         return 0;
61     }
62 }

  最后返回值為70.5,時間復雜度O(n+nlogn)

  在這道題的解題思路中,如果java有c++中的結構體會使后面的代碼不那么冗余,在java中需要實現comparable接口實現對象比較,稍微麻煩了些,但總體解題思路是一樣的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM