問題:有N件物品和一個容量爲V的揹包。第i件物品的重量是w[i],價值是v[i]。求 解將哪些物品裝入揹包可使這些物品的重量總和不超過揹包容量,且價值總和最大。
思路:創建兩個類。第一個類是商品類。商品們做個預處理。全部放到一個列表裏。再按照性價比排序。還有是揹包類。裏面存放着,最大可能價值,還能存放的重量,還有其父親類。總價值等。然後我們開始遍歷。無非就兩種情況。放入和不放入。亂入狀態加個1,不放入狀態加個0.然後都要求個最大可能價值。得出價值的方式就是挺的放後面的數,放爆了就放把爆之前剩餘的體積乘與後一個商品的平均單價。
最後求出一組最大可能性。時間複雜度時間複雜度爲O(2^n)。
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.PriorityQueue;
public class BagProblem
{
int[] price={10,14,20,9}; //每個東西的價格
int[] weight={5,7,10,3}; //每個東西的重量
int max=19; //最多存儲重量
List<Produce> list=new ArrayList<Produce>();//春芳商品的列表,按照價值從大到小排
PriorityQueue<Bag> heap=new PriorityQueue<Bag>((a,b)->{return (b.maxPrice-a.maxPrice)==0?b.reWeight-a.reWeight:b.maxPrice-a.maxPrice;});//存放當前揹包的狀態
List<Bag> result=new ArrayList<Bag>();//存放結果
BagProblem()
{
for(int i=0;i<weight.length;i++)
{
Produce produce=new Produce(price[i],weight[i],i);
list.add(produce);
}
Collections.sort(list,(a,b)->b.bw-a.bw);
Bag root=new Bag(max);//起點狀態
getUpPrice(root,list);
heap.add(root);
while(!heap.isEmpty())
{
Bag temp=heap.poll();
if(temp.i>=list.size()-1)
{
printAnswer(temp);
break;
}
//不放入
Bag notPut=new Bag(temp,temp.i+1);
if(!notPut.boon)
{
getUpPrice(notPut, list);
heap.add(notPut);
}
//放入
Bag putIn=new Bag(temp,list.get(temp.i+1),temp.i+1);
if(!putIn.boon)
{
getUpPrice(putIn, list);
heap.add(putIn);
}
}
}
//獲得最大價值
private void getUpPrice(Bag tempBag,List<Produce> list)
{
int re=tempBag.reWeight;
for(int i=tempBag.i+1;i<list.size();i++)
{
int temp=re-list.get(i).weight;
if(temp>=0)
{
re=temp;
tempBag.maxPrice+=list.get(i).price;
}else
{
tempBag.maxPrice+=list.get(i).price/list.get(i).weight*re;
break;
}
}
}
private void printAnswer(Bag temp)
{
for(int i=0;i<list.size();i++)
{
if(temp.stute.charAt(i)=='1')
System.out.println("放入價值爲"+list.get(i).price+",重量爲 "+list.get(i).weight+"的商品");
}
}
public static void main(String[] argc)
{
BagProblem test=new BagProblem();
}
}
//定義揹包類
class Bag
{
int sumPrice; //揹包內的總價格
int reWeight; //揹包內的剩餘
int maxPrice;//最大價值
int max; //最大承載重量
int i; //當前商品的序列值
boolean boon=false;//是否重量是否爆炸
String stute;
Bag father; //前一個揹包的狀態
Bag(){}
//初始狀態包
Bag(int max)
{
father=null;
sumPrice=0;
reWeight=max;
this.max=max;
this.i=-1;
stute="";
}
//構建一個不放入該項的包
Bag(Bag father,int i)
{
sumPrice=father.sumPrice;
reWeight=father.reWeight;
maxPrice=father.sumPrice;
max=father.max;
this.i=i;
stute=father.stute+"0";
this.father=father;
}
//構建一個放入的包
Bag(Bag father,Produce produce,int i)
{
sumPrice=father.sumPrice+produce.price;
reWeight=father.reWeight-produce.weight;
maxPrice=father.sumPrice+produce.price;
if(reWeight<0)
boon=true;
max=father.max;
this.i=i;
stute=father.stute+"1";
//maxPrice 到時候會由getUpPrice後期算出來的
this.father=father;
}
}
//定義商品類
class Produce
{
int id=0;
int price;
int weight;
int bw;
Produce(){}
Produce(int price,int weight,int id)
{
this.id=id;
this.price=price;
this.weight=weight;
bw=price/weight;
}
}