zoukankan      html  css  js  c++  java
  • 再谈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+="	";
    143             }
    144             str+="
    
    ";
    145         }
    146         return str;
    147     }
    148 }
    View Code
  • 相关阅读:
    logstash入门
    Gray Code LeetCode 89
    Longest Valid Parentheses Leetcode 32 一种奇特的解法
    写一个播放视频文件的ActiveX控件——MFC版(原创)
    一种用于网络播放的ActiveX控件
    《COM原理与应用》学习笔记——一个简单的COM组件的实现
    《COM原理与应用》学习笔记——COM的实现
    《COM原理与应用》题外话——C++虚函数表和delete this
    《COM原理与应用》学习笔记二——COM对象和COM接口的实现
    《COM原理与应用》学习笔记一
  • 原文地址:https://www.cnblogs.com/TQCAI/p/7679190.html
Copyright © 2011-2022 走看看