一、 問題描述
有一批集裝箱要裝上一艘載重為C的輪船。其中集裝箱i的重量為Wi。最優裝載問題要去確定在裝載體積不受限制的情況下,將極可能多的集裝箱裝上輪船。
二、 解題思路及所選算法策略的可行性分析
使用貪心算法。
問題描述為:
max∑Xi,∑WiXi<=C,Xi∈{0,1} 1<=i<=n
其中,變量Xi=0表示不裝入集裝箱i,Xi=1表示裝入集裝箱i。
貪心選擇性質:
設集裝箱已依其重量從小到大排序,(X1,X2,…,Xn)是最優裝問題的一個最優解。又設k=min{i|Xi=1}。易知,如果給定的最優裝載問題有解,則1<i<=n,i!=k,則
∑WiYi = Wi - Wk + ∑WiXi <= ∑WiXi <= C
因此,(Yz,Y2,…,Yn)是所給最優裝載問題的可行解。
另一方面,由∑Yi = ∑Xi知,(Y1,Y2,…,Yn)是滿足貪心選擇性質的最優解。
最優子結構性質:
設(X1,X2,…,Xn)是最優裝載問題的滿足貪心選擇性質的最優解,則容易知道,X1=1,且(X2,…,Xn)是輪船載重量為C-W1,待裝載集裝箱為{2,3,…,n}時相應最優集裝箱問題的最優解。也及時說,最優集裝箱裝載問題具有最優子結構性質。
三、 代碼描述及復雜度分析
Loading(float c, float[]w, int[] x)
{
創建集裝箱數組,存放每個集裝箱重量及其序號;
按集裝箱重量從小到大排序;
有小到大依次判斷是否可入箱;
返回輪船上箱子總重量;
}
四、代碼實現
package 貪心算法; import 分治法.dcPoint; class Element implements Comparable{ float w; int i; public Element(float ww, int ii) { w=ww; i=ii; } public int compareTo(Object x) { float xw=((Element)x).w; if(w<xw) return -1; if(w==xw) return 0; return 1; } } class MergeSort{ public static void mergeSort(Element[] a){ Element[] tempArray = new Element[a.length]; mergeSort(a, tempArray, 0, a.length - 1); } private static void mergeSort(Element[] a, Element [] tempArray, int left, int right){ if(left < right){ int center = (left + right) >> 1; //分治 mergeSort(a, tempArray, left, center); mergeSort(a, tempArray, center + 1, right); //合並 merge(a, tempArray, left, center + 1, right); } } private static void merge(Element [] a, Element [] tempArray, int leftPos, int rightPos, int rightEnd){ int leftEnd = rightPos - 1; int numOfElements = rightEnd - leftPos + 1; int tmpPos = leftPos; //游標變量, 另兩個游標變量分別是leftPos 和 rightPos while(leftPos <= leftEnd && rightPos <= rightEnd){ if(a[leftPos].w <= a[rightPos].w) tempArray[tmpPos++] = a[leftPos++]; else tempArray[tmpPos++] = a[rightPos++]; } while(leftPos <= leftEnd) tempArray[tmpPos++] = a[leftPos++]; while(rightPos <= rightEnd) tempArray[tmpPos++] = a[rightPos++]; //將排好序的段落拷貝到原數組中 System.arraycopy(tempArray, rightEnd-numOfElements+1, a, rightEnd-numOfElements+1, numOfElements); } } public class 最優裝載{ public static float loading(float c, float[]w, int[]x) { int n=w.length; Element[]d=new Element[n]; for(int i=0; i<n; i++) d[i]=new Element(w[i],i); MergeSort.mergeSort(d); float opt=0; for(int i=0;i<n;i++) x[i]=0; for(int i=0;i<n;i++) { if(w[i]<=c){ x[d[i].i]=1; opt+=d[i].w; c-=d[i].w; }else break; } return opt; } public static void main(String[] args) { float weight= (float) 100.00; float w[]={1,5,10,14,15,16,20,18,23,32,56,72,85}; int x[]=new int[w.length]; System.out.println("貨物總重量為:"+loading(weight, w, x)); System.out.print("裝入集裝箱為:"); for(int i=0; i<w.length; i++) if(x[i]==1) System.out.print(i+1+" "); } }
五、代碼運行結果截圖