演算法學習——貪心演算法之可拆揹包
阿新 • • 發佈:2018-11-09
演算法描述
已知道n種物品和一個可容納c重量的揹包,第i種物品的重量為wi,價值為pi,裝包的時候可以把物品拆開(即可只裝每種物品的一部分),設計如何裝包,使裝包所得整體的價值最高?
演算法思路
首先,我們要知道,n種物品以及他們對應的價值,都是由使用者輸入的
我們使用貪心演算法,每一步取最大效益的物品放入揹包之中(及單位價值為最高的物品 單位價值=pi/wi)
由以上思路,我們可以定義一個二維陣列來接收使用者輸入的數值
w[i][0] 代表了第i種物品的重量(即wi)
w[i][1] 代表了第i種物品的價值(即pi)
w[n][m] n範圍為1~n m範圍為0~1
這裡需要注意,陣列下標是從0開始的,我們的n是從1開始的,空出了一個0,所以我們定義n應該定義為n+1 這裡應該不難理解,n+1的話,下標就是0~n,我們需要1~n這n個位置
定義為
double[][] w = new double[n+1][2]
除了上面所說,我們還需一個
Flag類
來存放單位價值以及該單位價值對應的第i個物品(也就是下標)我們將單位價值計算得出後作為
Flag類
的成員變數content
,以及下標作為Flag類
中的成員變數flag
,之後使用ArrayList
存放多個Flag類
之後,將單位價值存放在一個一維陣列中,使用排序,從小到大排序
得到排序之後的一維陣列,依次與
ArrayList
中的每一個Flag類
的content
作比較,得到其對應的下標,存入到棧中之後,棧頂就是單位價值最大的所對應的下標,依次取出來(即實現了每次都是取到的物品都是單位價值最大的),進行相關的運算即可
演算法實現
Scanner scanner = new Scanner(System.in); double cost = 0;//記錄當揹包滿的時候所達到的價值 System.out.println("輸入物品個數n:"); int n = scanner.nextInt(); System.out.println("輸入揹包可裝容量c:"); double c = scanner.nextDouble(); double temp[] = new double[n+1]; double w[][] = new double[n+1][2]; ArrayList<Flag> list = new ArrayList<Main.Flag>(); for(int i=1;i<=n;i++){ System.out.println("w"+i+"重量:"); w[i][0] = scanner.nextDouble(); System.out.println("w"+i+"價值:"); w[i][1] = scanner.nextDouble(); temp[i]=w[i][1]/w[i][0]; } scanner.close(); Stack<Integer> stack = new Stack<Integer>(); //存入到list中,儲存原來的下標和內容 for(int i=1;i<temp.length;i++){ Flag flag = new Flag(i, temp[i]); list.add(flag); } double t = 0; Arrays.sort(temp);//使用java中自帶的快速排序 //將原來的下標存入進棧中,處於棧頂的是單位價值最高的該物品的下標 for(int i=1;i<temp.length;i++){ for(Flag flag : list){ if(flag.getContent()==temp[i]){ stack.push(flag.getFlag()); } } } while(!stack.isEmpty()){ int i =stack.pop();//出棧 c = c -w[i][0]; if(c<=0){ c = c+w[i][0];//加回之前所減去的內容,計算百分比 double a = (c/w[i][0])*100; DecimalFormat format = new DecimalFormat("##.#"); System.out.println("裝入"+"第"+i+"種物品的百分之"+format.format(a)+",重量為"+w[i][0]+",價值為"+w[i][1]); cost = cost+w[i][1]*(a/100); System.out.println("最大價值為"+format.format(cost)); break; }else{ cost = cost+w[i][1]; } System.out.println("裝入"+"第"+i+"種物品"+",重量為"+w[i][0]+",價值為"+w[i][1]); } } //定義了一個Flag類,存放原來的座標以及單位價值 public static class Flag{ int flag; double content; public Flag(int flag,double content){ this.flag = flag; this.content= content; } public int getFlag(){ return this.flag; } public double getContent(){ return this.content; } }