题目:n个物品,第i个物品重量wi,价值vi,放入装在能力为c的背包中,物品放一个或不放。求装载价值最大的装载方法。
package hello;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner s=new Scanner(System.in);
String str=s.nextLine();
double max=s.nextInt(),maxvalues=0,maxcw=max;
String []s2=str.split(",");
//建立数组完毕
int [][]c=new int [(s2.length)/2][2];
for(int i=0;i<s2.length;i=i+2) {
c[i/2][0]=Integer.parseInt(s2[i]);
c[i/2][1]=Integer.parseInt(s2[i+1]);
}
double []a=new double[c.length];
for(int i=0;i<a.length;i++) {
a[i]=(double)c[i][0]/c[i][1];
}
//输出排序前结果
for(int i=0;i<c.length;i++) {
System.out.printf(" %d ",c[i][0]);
}System.out.printf("\n");
for(int i=0;i<c.length;i++) {
System.out.printf(" %d ",c[i][1]);
}System.out.printf("\n");
for(int i=0;i<a.length;i++) {
System.out.printf(" %.2f",a[i]);
}System.out.printf("\n");
//利用快速排序得排序后结果
Quicksort sort=new Quicksort(a,c,0,a.length);
System.out.printf("排序后的结果\n");
for(int i=0;i<c.length;i++) {
System.out.printf(" %d ",c[i][0]);
}System.out.printf("\n");
for(int i=0;i<c.length;i++) {
System.out.printf(" %d ",c[i][1]);
}System.out.printf("\n");
for(int i=0;i<a.length;i++) {
System.out.printf(" %.2f",a[i]);
}System.out.printf("\n");
//以下是回朔算法求得的结果。
double bound=maxvalues;//maxcw是最大装载量,bound是上界量。
double []p=new double[7];
p[0]=maxcw;
double values=0;//0是最大装载量,1是当前装载量,2是当前最优价值,3是最终最优价值,
//4是最高价值,用作上界函数,5是当前树,6是物体总价值
for(int i=0;i<c.length;i++) {
values+=c[i][1];
}
p[6]=values;p[4]=maxvalues;p[5]=0.0;
for(int i=0;i<a.length;i++) {
a[i]=0;
}
double []trace=new double[a.length];//引入trace数组永久记录最优解的数组。
double back=backtrack(c,p,a,trace);
for(int i=0;i<a.length;i++) {
System.out.printf(" %.2f",trace[i]);
}System.out.printf("\n");
System.out.printf("maxvalues: %.2f",p[3]);
}
public static double backtrack(int c[][],double []p,double a[],double trace[]) {
if(p[2]>p[3]) {
p[3]=p[2];
for(int i=0;i<a.length;i++) {
trace[i]=a[i];
// System.out.printf(" **%.2f",trace[i]);
}
}
if((int)(p[5])<c.length) {
if(p[1]+c[(int)p[5]][1]<=p[0]) { //背包为装满,选择并尽进入进入左子树
p[1]+=c[(int) p[5]][1];
p[6]-=c[(int) p[5]][0];
p[2]=p[2]+c[(int) p[5]][0];
a[(int) p[5]]=1;
p[5]=p[5]+1;
backtrack(c,p,a,trace);//进入左子树
if((int) p[5]>0)//退出左子树后,就要回复现场,就上一层树去掉,然后进行
p[5]=p[5]-1;
p[1]-=c[(int) p[5]][1];
p[6]+=c[(int) p[5]][0];
p[2]=p[2]-c[(int) p[5]][0];
a[(int) p[5]]=0;
p[5]=p[5]+1;
if(p[6]+p[2]>p[3]) //剪枝函数,当剩余物品的总价值加当前价值比最优价值还小时,进行剪枝操作。
backtrack(c,p,a,trace);//进入右子树
}
}
return 0.0;
}
}
class Quicksort{
Quicksort(){};
Quicksort(double a[],int c[][],int p,int r){
if(p<r) {
int q=partition(a,c,p,r);
quicksort(a,c,p,q);
quicksort(a,c,q+1,r);
}
}
public void quicksort(double[] a,int c[][], int p, int r) {
// TODO Auto-generated method stub
if(p<r) {
int q=partition(a,c,p,r);
quicksort(a,c,p,q);
quicksort(a,c,q+1,r);
}
}
public int partition(double a[],int c[][],int p,int r) {
int i=p;
int j=p;
int k=p;
double x=a[i];
int point=0;
double b[] =new double [a.length];
int [] [] c1=new int [a.length][a.length];
for(i=p;i<r;i++) {
if(a[i]>=x) {
a[j]=a[i];
c[j]=c[i];
j++;
}
if(a[i]<x) {
b[k]=a[i];
c1[k]=c[i];
k++;
}
}
k=p;point=j-1;
double temp=a[point];
a[point]=a[p];a[p]=temp;
int temp0=c[point][0];
c[point][0]=c[p][0];c[p][0]=temp0;
int temp1=c[point][1];
c[point][1]=c[p][1];c[p][1]=temp1;
for(j=point+1;j<r;j++) {
a[j]=b[k];
c[j]=c1[k];
k++;
}
return point;
}
}
结果:
1,10,2,5,12,4,12,3,78,2
6
1 2 12 12 78
10 5 4 3 2
0.10 0.40 3.00 4.00 39.00
排序后的结果
78 12 12 2 1
2 3 4 5 10
39.00 4.00 3.00 0.40 0.10
1.00 1.00 0.00 0.00 0.00
maxvalues: 90.00