问题描述:
需对容量为c 的背包进行装载。从n 个物品中选取装入背包的物品,每件物品i 的重量为wi ,价值为pi 。对于可行的背包装载,背包中物品的总重量不能超过背包的容量,最佳装载是指所装入的物品价值最高。
输入:
多个测例,每个测例的输入占三行。第一行两个整数:n(n<=10)和c,第二行n个整数分别是w1到wn,第三行n个整数分别是p1到pn。
n 和 c 都等于零标志输入结束。
输出:
每个测例的输出占一行,输出一个整数,即最佳装载的总价值
输入样例:
1 2
1
1
2 3
2 2
3 4
0 0
输出样例:
1
4
//回溯法实现01背包问题
import java.util.Scanner;
public class Main
{
static int c;
static int n;
static int []w;
static int []p;
static int cw;
static int cp;
static int bestp;
public static void main(String args[])
{
Scanner s=new Scanner(System.in);
//n=Integer.parseInt(s.next());
//c=Integer.parseInt(s.next());
while(s.hasNext())
{
String line=s.nextLine();//读入c和n
String[] sArray=line.split(" ");
n=Integer.parseInt(sArray[0]);
c=Integer.parseInt(sArray[1]);
if(n==0&&c==0)
return;
if(n==0)
{
System.out.println(0);
continue;
}
line=s.nextLine();//读入w的行
sArray=line.split(" ");
w=new int[sArray.length];
for(int j=0;j<sArray.length;j++)
{
w[j]=Integer.parseInt(sArray[j]);
}
line=s.nextLine();//读入p的行
sArray=line.split(" ");
p=new int[sArray.length];
for(int j=0;j<sArray.length;j++)
{
p[j]=Integer.parseInt(sArray[j]);
}
System.out.println((Knapsack(p,w,c)));
}
}//Main
///////////////////////////////////////////////////////////////////////////////////////////////
private static class Element implements Comparable
{
int id;//物品编号
double d;
private Element(int idd,double dd)
{
id=idd;
d=dd;
}
public int CompareTo(Object x)
{
double xd=((Element)x).d;
if(d<xd)return -1;
if(d==xd)return 0;
return 1;
}
public boolean equals(Object x)
{
return d==((Element)x).d;
}
public int compareTo(Object arg0) {
// TODO Auto-generated method stub
return 0;
}
}//Element
////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
public static int Knapsack(int []pp,int []ww,int cc)
{
c=cc;
n=pp.length-1;
//n=pp.length;
cw=0;
cp=0;
bestp=0;
Element []q=new Element[n+1];
//for(int i=1;i<=n;i++)
//q[i-1]=new Element(i,pp[i]/ww[i]);
for(int i=0;i<=n;i++)
q[i]=new Element(i,pp[i]/ww[i]);
//对q[]从大到小排序
for(int m=0;m<q.length;m++)
{
for(int j=m+1;j<q.length;j++)
{
if(q[m].d<q[j].d)
{
// int temp=m;
// m=j;
// j=temp;
int temp1=q[m].id;
q[m].id=q[j].id;
q[j].id=temp1;
double temp2=q[m].d;
q[m].d=q[j].d;
q[j].d=temp2;
}
}
}
p=new int[n+1];
w=new int[n+1];
for(int j=0;j<=n;j++)
{
p[j]=pp[q[j].id];
w[j]=ww[q[j].id];
}
backtrack(0);
return bestp;
}//knapsnack
static void backtrack(int i)
{
if(i>n)
{
bestp=cp;
return;
}
if(cw+w[i]<=c)
{
cw+=w[i];
cp+=p[i];
backtrack(i+1);
cw-=w[i];
cp-=p[i];
}
if(bound(i+1)>bestp)
backtrack(i+1);
}//backtrack
private static double bound(int i)
{
double cleft=c-cw;
double bound=cp;
while(i<=n&&w[i]<=cleft)
{
cleft-=w[i];
bound+=p[i];
i++;
}
if(i<=n)
bound+=p[i]*cleft/w[i];
return bound;
}//bound
}