再谈01背包 | 使用【跳跃点集合】代替【求解矩阵】解题

 

 

上文链接:9大背包第一弹 | 01背包


 

 

 

输入:

1         double []w={2,2,6,5,4};
2         double []v={6,3,5,4,6};
3         double weight=10;
4         _01package problem=new _01package(w,v,weight);

输出:

1 应该放入背包的物品:5 2 1 

【跳跃点集合】Java代码:

 1 class _01package{
 2     //价值、重量
 3     int [][] matrix;
 4     List<Integer> solve=new ArrayList<Integer>();
 5     //使用跳跃点集合解题
 6     _01package(double [] w,double [] v,double weight){
 7         int len=w.length;
 8         class struct{    //新建一个二元组,表示当背包容量为w时,背包的价值为v
 9             double w=0;
10             double v=0;
11             struct(){}
12             struct(double w,double v){this.w=w;this.v=v;}
13         }
14         List<struct> p[]=new ArrayList[len+1];//表示全部的跳跃点 C[i][j]
15         List<struct> q[]=new ArrayList[len+1];//表示跳跃点       C[i][j-wi]+vi
16         double[] W=new double[len+1];
17         double[] V=new double[len+1];
18         W[0]=0;
19         V[0]=0;
20         int i,j,k;
21         for(i=1;i<=len;i++) W[i]=w[i-1];
22         for(i=1;i<=len;i++) V[i]=v[i-1];
23         p[0]=new ArrayList<struct>();
24         p[0].add(new struct(0,0));//初始变量
25         for(i=1;i<=len;i++){//依次放入物品
26             //q[i-1]=p[i-1]⊕(wi,vi)        解得q,跳跃点C[i][j-wi]+vi
27             q[i-1]=new ArrayList<struct>();
28             for(j=0;j<p[i-1].size();j++){
29                 struct tmp=new struct(p[i-1].get(j).w+W[i],p[i-1].get(j).v+V[i]);
30                 
31                 q[i-1].add(tmp);
32             }
33             //p[i]=p[i-1]∪q[i-1]            取并集
34             p[i]=new ArrayList<struct>();
35             p[i].addAll(p[i-1]);
36             p[i].addAll(q[i-1]);
37             int b;
38             b=0;
39             //按照w对p进行重排序
40             int pLen=p[i].size();
41             for(j=1;j<pLen;j++)            //冒泡排序
42                 for(k=0;k<pLen-j;k++)
43                     if(p[i].get(k).w>p[i].get(k+1).w){//应交换
44                         struct tmp_p=p[i].get(k);
45                         struct tmp=new struct(tmp_p.w,tmp_p.v);
46                         p[i].set(k, p[i].get(k+1));
47                         p[i].set(k+1, tmp);
48                     }
49             
50             //对p执行检查操作,查看是否有【超限】和【不满足递增】的情况
51             double preV=0;
52             for(j=0;j<p[i].size();){
53                 if(p[i].get(j).w>weight    //【超限】
54                 ||    p[i].get(j).v<preV    ){//【不满足递增】
55                     
56                     p[i].remove(j);//删除j元素
57                 }else{
58                     preV=p[i].get(j).v;
59                     j++;
60                     
61                 }
62             }
63         }
64         //对p进行回溯
65         int t=p[len].size()-1;//
66         double wx=p[len].get(t).w;//wx:初始化为最大重量
67         double vx=p[len].get(t).v;//wv:初始化为最大价值
68         for(j=len;j>0;j--){//
69             for(k=0;k<p[j].size();k++){
70                 double tw=p[j].get(k).w;
71                 double tv=p[j].get(k).v;
72                 if(tw+W[j]==wx && tv+V[j]==vx){
73                     wx=tw;
74                     vx=tv;
75                     solve.add(j);
76                 }
77             }
78         }
79         System.out.print("应该放入背包的物品:");
80         for(i=0;i<solve.size();i++) System.out.print(solve.get(i)+" ");
81         System.out.println();
82     }

完整代码:

  1 import java.util.*;
  2 
  3 public class Main {
  4 
  5     public static void main(String[] args) {
  6         // TODO Auto-generated method stub
  7         double []w={2,2,6,5,4};
  8         double []v={6,3,5,4,6};
  9         double weight=10;
 10         _01package problem=new _01package(w,v,weight);
 11         
 12         
 13     }
 14 
 15 }
 16 
 17 class _01package{
 18     //价值、重量
 19     int [][] matrix;
 20     List<Integer> solve=new ArrayList<Integer>();
 21     //使用跳跃点集合解题
 22     _01package(double [] w,double [] v,double weight){
 23         int len=w.length;
 24         class struct{    //新建一个二元组,表示当背包容量为w时,背包的价值为v
 25             double w=0;
 26             double v=0;
 27             struct(){}
 28             struct(double w,double v){this.w=w;this.v=v;}
 29         }
 30         List<struct> p[]=new ArrayList[len+1];//表示全部的跳跃点 C[i][j]
 31         List<struct> q[]=new ArrayList[len+1];//表示跳跃点       C[i][j-wi]+vi
 32         double[] W=new double[len+1];
 33         double[] V=new double[len+1];
 34         W[0]=0;
 35         V[0]=0;
 36         int i,j,k;
 37         for(i=1;i<=len;i++) W[i]=w[i-1];
 38         for(i=1;i<=len;i++) V[i]=v[i-1];
 39         p[0]=new ArrayList<struct>();
 40         p[0].add(new struct(0,0));//初始变量
 41         for(i=1;i<=len;i++){//依次放入物品
 42             //q[i-1]=p[i-1]⊕(wi,vi)        解得q,跳跃点C[i][j-wi]+vi
 43             q[i-1]=new ArrayList<struct>();
 44             for(j=0;j<p[i-1].size();j++){
 45                 struct tmp=new struct(p[i-1].get(j).w+W[i],p[i-1].get(j).v+V[i]);
 46                 
 47                 q[i-1].add(tmp);
 48             }
 49             //p[i]=p[i-1]∪q[i-1]            取并集
 50             p[i]=new ArrayList<struct>();
 51             p[i].addAll(p[i-1]);
 52             p[i].addAll(q[i-1]);
 53             int b;
 54             b=0;
 55             //按照w对p进行重排序
 56             int pLen=p[i].size();
 57             for(j=1;j<pLen;j++)            //冒泡排序
 58                 for(k=0;k<pLen-j;k++)
 59                     if(p[i].get(k).w>p[i].get(k+1).w){//应交换
 60                         struct tmp_p=p[i].get(k);
 61                         struct tmp=new struct(tmp_p.w,tmp_p.v);
 62                         p[i].set(k, p[i].get(k+1));
 63                         p[i].set(k+1, tmp);
 64                     }
 65             
 66             //对p执行检查操作,查看是否有【超限】和【不满足递增】的情况
 67             double preV=0;
 68             for(j=0;j<p[i].size();){
 69                 if(p[i].get(j).w>weight    //【超限】
 70                 ||    p[i].get(j).v<preV    ){//【不满足递增】
 71                     
 72                     p[i].remove(j);//删除j元素
 73                 }else{
 74                     preV=p[i].get(j).v;
 75                     j++;
 76                     
 77                 }
 78             }
 79         }
 80         //对p进行回溯
 81         int t=p[len].size()-1;//
 82         double wx=p[len].get(t).w;//wx:初始化为最大重量
 83         double vx=p[len].get(t).v;//wv:初始化为最大价值
 84         for(j=len;j>0;j--){//
 85             for(k=0;k<p[j].size();k++){
 86                 double tw=p[j].get(k).w;
 87                 double tv=p[j].get(k).v;
 88                 if(tw+W[j]==wx && tv+V[j]==vx){
 89                     wx=tw;
 90                     vx=tv;
 91                     solve.add(j);
 92                 }
 93             }
 94         }
 95         System.out.print("应该放入背包的物品:");
 96         for(i=0;i<solve.size();i++) System.out.print(solve.get(i)+" ");
 97         System.out.println();
 98     }
 99     
100     //使用求解矩阵进行求解
101     _01package(int [] w,int [] v,int weight){
102         int i,j;
103         int len=w.length;
104         matrix=new int[len+1][weight+1];//构建求解数组
105         for(i=0;i<weight+1;i++) matrix[0][i]=0;//第一行为0
106         for(i=0;i<len+1;i++) matrix[i][0]=0;//第一列为0
107         //动态规划
108         for(i=1;i<len+1;i++){            //从上到下【不断将物品放入背包】【i】代表物品
109             for(j=1;j<weight+1;j++){    //从左到右【背包的容量不断扩充】【j】代表当前容量
110                 if(j>w[i-1]){//【当前背包容量】比【将要放入的物品】的【重量】大
111                     matrix[i][j]=Math.max
112                        (matrix[i-1][j],                    //选择不放
113                         matrix[i-1][j-w[i-1]]+v[i-1]);    //让背包腾出w[i-1],即【当前物品】的【重量】的空间,选择放入
114                 }else{        //放不进。拷贝【上一个物品】的重量
115                     matrix[i][j]=matrix[i-1][j];
116                 }
117             }
118         }
119         System.out.println("求解矩阵:");
120         System.out.print(this);
121         //回溯
122         j=weight;//最后一列
123         for(i=len;i>0;i--){//对行进行遍历
124             if(matrix[i][j]>matrix[i-1][j]){//增减物品时,价值增加了。说明放入了物品
125                 j-=w[i-1];
126                 solve.add(i);
127             }
128         }
129         System.out.print("应该放入背包的物品:");
130         for(i=0;i<solve.size();i++) System.out.print(solve.get(i)+" ");
131         System.out.println();
132     }
133 
134     public String toString(){
135         int row = matrix.length;//行数
136         int col =matrix[0].length;//列数
137         String str=new String("");
138         int i,j;
139         for(i=0;i<row;i++){
140             for(j=0;j<col;j++){
141                 str+=Integer.toString(matrix[i][j]);
142                 str+="\t";
143             }
144             str+="\n\n";
145         }
146         return str;
147     }
148 }
View Code

 

posted @ 2017-10-16 22:17  TQCAI  阅读(1307)  评论(0编辑  收藏  举报