您的位置:首页 > 理论基础 > 数据结构算法

数据结构之贪心算法(背包问题的思考)

2017-07-27 11:09 239 查看
package com.lip.datastructure;  

/** 

 *贪心算法:装箱问题的思考 

 * @author Lip 

 *装箱问题可以是时间调问题的延伸,当一个箱子没有容积限制,那么就是时间调度问题 

 *在时间调度问题中:存在两个可以讨论的问题。1.平均最短时间 2.总的最短时间 

 *这两个问题都和装箱问题中问题如此类似。 

 */  

/* 

 * 上面是我理解的装箱问题,本来是想说背包问题的 

 * 背包问题的描述:有N件物品和一个容量为V的背包。第i件物品的重量是w[i],价值是v[i]。 

 * 求解将哪些物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大。 

 */  

/* 

 * 贪心算法可以解决装箱问题,也可以解决背包问题,但是由贪心算法求出的解的可能不是最优解。 

 * 如:事实上,作为一个理性人,我们都是贪心的。当你面对一堆金银珠宝的时候,你有一个背包,你的选择肯定会是优先选择性价比最高的珠宝。 

 * 那么,从这个角度来说,我们可以用贪心算法来解决背包问题,即使不是问题的最优解。但是,这个解却是一个理人人的通常选择的贪心 策略。 

 */  

public class Pack  

    {  

  

        public static void main(String[] args)  

            {  

                /***********************装箱问题********************************/  

                int []weight={8,7,5,4,4,3,3,2,2,2,1};  

                int []box={12,12,12,10};  

                int []result=loadInBox(Type.OFFLINE, box, weight);  

                  

                for(int i=0;i<box.length;i++)  

                    {  

                        System.out.println("第"+(i+1)+"号箱子货物:");  

                        print(weight, result, i+1);  

                        System.out.println();  

                    }  

//              /***********0-1背包问题**************/  

//              int []weight={2,3,4,6,2,5,4,3,8,1};  

//              int []value={7,8,13,20,17,9,12,15,5,5};  

//              int c=20;  

//              int []position=loadInPack(c, value, weight);  

//              int sum=0;  

//              int sumW=0;  

//              for(int i=0;i<position.length;i++)  

//                  {  

//                      if(position[i]!=0)  

//                          {  

//                            sumW+=weight[position[i]-1];  

//                            sum+=value[position[i]-1];  

//                            System.out.println(position[i]+"->("+weight[position[i]-1]+","+value[position[i]-1]+")");  

//                          }  

//                      else break;  

//                  }  

//              System.out.println("最大的收益为:"+sum);  

//              System.out.println("有多少空间没有利用:"+(c-sumW));  

                

  

            }  

        /***********************装箱问题********************************/  

        /** 

         * @param type  

         * @param box 箱子 

         * @param weight 货物重量 

         * @return 

         */  

        public static int[]loadInBox(Type type,int box[],int []weight)  

        {  

            int []result=new int[weight.length];  

            Sort.quickSort(weight);  

            int sum=0;  

            for(int i=0;i<weight.length;i++)  

                sum+=weight[i];  

            int sum2=0;//箱子总容积  

            for(int i=0;i<box.length;i++)  

                sum2+=box[i];  

            if(sum>sum2)//艹,箱子不够  

                return null;  

            if(type==Type.OFFLINE)//给每个箱子都分配一个最大的货物  

                {  

                    for(int i=weight.length-1,j=0;i>-1;i--)  

                        {  

                            int find=box.length;  

                            while(weight[i]>box[j])//不可以装  

                                {  

                                    j=(j+1)%box.length;  

                                    find--;  

                                    if(find==0)//箱子不够  

                                        {  

                                        System.out.println("------背包不够---------");  

                                          return null;  

                                        }  

                                }  

                            result[i]=j+1;  

                            box[j]-=weight[i];  

                            j=(j+1)%box.length;  

                        }  

                }  

            else if(type==Type.ONLINE)//先装一个箱子  

                {  

                   for(int i=0;i<box.length;i++)  

                       {  

                          //box[i] 箱子的当前剩余,也就是还可以装的货物  

                           for(int j=weight.length-1;j>-1;j--)//一直装,直到装满  

                              {  

                                  if(box[i]==0)//该箱子装满了  

                                      break;  

                                  if(result[j]==0&&weight[j]<=box[i])//该货物没有被装  

                                      {  

                                          box[i]-=weight[j];  

                                          result[j]=i+1;  

                                      }  

                              }  

                       }  

                }  

            return result;  

        }  

        public static void print(int []weight,int []result,int k)  

        {  

            for(int i=0;i<result.length;i++)  

                if(result[i]==k)  

                    System.out.print(weight[i]+" ");  

        }  

        /** 

         *  

         * @author Lip 

         * 解决装箱问题有两种方式,一种是联机,一种是脱机。 

         * 所谓联机就是将一个箱子完全放满货物后,再开始处理下一个箱子 

         * 脱机就是将所有的货物都读取进来,按照从大到小的顺序将货物分配给箱子,直到各个箱子都被装满 

         */  

        public enum Type  

        {  

            ONLINE,OFFLINE;  

        };  

        /**************************0-1背包问题(贪心算法)************************************/  

        /** 

         *  

         * @param c 背包容量 

         * @param value 每个物品的价值 

         * @param weight 每个物品的容积 

         */  

        /* 

         * 当使用贪心算法解决背包问题时,那么考虑到贪心策略,就是要保证当前选择是最好的。 

         * 那么另外一个参考量“性价比”就被引用,p=value/weight 

         * 一直选择性价比最高的物品放入到背包中,直至背包被放满 

         */  

        public static int[] loadInPack(int c,int[]value,int []weight)  

        {  

  

            double []price=new double[value.length];//性价比  

            int []position=new int[value.length];  

            int p=0;  

            for(int i=0;i<value.length;i++)  

                price[i]=(double)value[i]/weight[i];  

            //开始装了  

            while(c>0)  

                {  

                    double max=-1;  

                    int pos=-1;  

                    for(int i=0;i<price.length;i++)//找性价比最高的,且没有被装到背包中的  

                        {  

                            if(price[i]!=-1&&price[i]!=0&&max<price[i])  

                                {  

                                    max=price[i];  

                                    pos=i;  

                                }  

                        }  

                    if(pos==-1)//虽然剩下空间,但是再也找不到合适的了  

                        break;  

                    if(c>=weight[pos])  

                        {  

                            c-=weight[pos];  

                            price[pos]=-1;//已经装过  

                            position[p]=pos+1;  

                            p++;  

                        }  

                    else   

                        {  

                            price[pos]=0;//装不下,但是可以装比这个更小的  

                        }  

                }  

              

            return position;  

              

        }  

    }  

 

 贪婪算法运行效果:
    脱机装箱:
        


   联机装箱:
      


  贪心算法解决0-1背包问题:
     
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息