01背包问题_回溯法_java实现

问题描述:


需对容量为的背包进行装载。从个物品中选取装入背包的物品,每件物品的重量为wi ,价值为pi 。对于可行的背包装载,背包中物品的总重量不能超过背包的容量,最佳装载是指所装入的物品价值最高。

输入:

多个测例,每个测例的输入占三行。第一行两个整数:nn<=10)和c,第二行n个整数分别是w1wn,第三行n个整数分别是p1pn
和 都等于零标志输入结束。

输出:

每个测例的输出占一行,输出一个整数,即最佳装载的总价值

输入样例:

2
1
1
3
2
4
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
}


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值