zoukankan      html  css  js  c++  java
  • Arithmetic_Thinking -- greedy algorithm

    贪心算法--就是一种寻找局部最优解的情况,然后整合成整体最优解的情况

    简单的例子:买菜的找钱,现在有1元,5角,1角的硬币,要找给别人2元7角,现在是怎么才能以最少的硬币量找给别人,肯定是先来两个1元的,再来1个5角的,最后两个1角的,但是,这个是我们一眼就能想到的,如何将它抽象成算法的思想呢?

    第一步:先找到面值不超过2元7角的最大的硬币,只有1元,还剩下1元7角

    第二步:再找到面值不超过1元7角的最大的硬币,只有1元,还剩下7角,

    第三步,找到面值不超过7角的最大的硬币,有5角,还剩2角

    第四步,找到面值不超过2角的最大的硬币,有1角,还剩1角

    第五步,找到面值不超过1角的最大的硬币,有1角,还剩0角

    第六步,找到面值不超过0角的最大的硬币,没有,结束

    以上其实就是算法的思想,看似很简答,其实也是比较繁琐,最主要的就是找到当前下的最优的解,不管整体怎么样,思想也很简单,但是,什么时候去使用贪心算法,这点就很难了,要满足两个条件,能够找到当前的最优的解,其次最优子结构体是整体最优解的一部分,要使用贪心算法之前你得先要验证是不是可以来使用这个。。。这一点就比较鸡肋了,可是,不管怎么来说,最后能不能得到最优解,贪心算法都是执行效率很高的算法思想。

    说了这么多,实践才是验证真理的唯一标准,那我们就来愉快的做个题吧。。。

    package thinking;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Scanner;
    
    import org.junit.Test;
    
    /* QUESTION : optimal loading problem
     * DESCRIBTION : Now we have some boxs need to be loaded into a ship which the limit of its load capacity is C ,and
     *                 every weight of box is designated by the user. The Volume(体积) of this ship isn't limit. So how can 
     *                 we load boxes as many as possible? 
     * 
     * */
    class Ship{
        private int capacity;
        public void setCapacity(int capacity) {
            this.capacity = capacity;
        }
        public int getCapacity() {
            return capacity;
        }
    }
    
    class Box{
        private int weight;
        public void setWeight(int weight) {
            this.weight = weight;
        }
        public int getWeight() {
            return weight;
        }
    }
    
    public class Greedy {
        Ship ship = new Ship();
        Box box1 = new Box();
        Box box2 = new Box();
        Box box3 = new Box();
        Box box4 = new Box();
        Box box5 = new Box();
        @Test
        public void lookingForTheBestChoise(){
            
            // step 1 : initialize the info of ship and boxes
            System.out.println("please input the capacity of ur ship!");
            Scanner scanner = new Scanner(System.in);
            int capacity = scanner.nextInt();
            ship.setCapacity(capacity);
            System.out.println("please input the werght of ur boxes(5)!");
            int b1 = scanner.nextInt();
            int b2 = scanner.nextInt();
            int b3 = scanner.nextInt();
            int b4 = scanner.nextInt();
            int b5 = scanner.nextInt();
            box1.setWeight(b1);
            box2.setWeight(b2);
            box3.setWeight(b3);
            box4.setWeight(b4);
            box5.setWeight(b5);
            List<Box> boxes = new ArrayList<Box>();
            boxes.add(box1);
            boxes.add(box2);
            boxes.add(box3);
            boxes.add(box4);
            boxes.add(box5);
                    
            List<Box> sortedList = sort(boxes);
            
            // step 2 : looking for the best solution step by step
            int index = 0;
            while(capacity != 0){
                if(sortedList.get(0).getWeight() > capacity){
                    System.out.println("ur capacity of ship is too light!");
                    System.exit(0);
                }else{
                    if(sortedList.get(index).getWeight() < capacity){
                        System.out.print(sortedList.get(index).getWeight());
                        capacity = capacity-sortedList.get(index).getWeight();
                        index++;
                    }else{
                        System.out.println("no more can be loaded");
                        System.exit(0);
                    }
                }
            }
            
        }
        
        List<Box> sort(List<Box> boxes){
            //List<Box> sortedList = new ArrayList<Box>();
            for(int i = 0; i<boxes.size(); ++i){
                for(int j = 0; j < boxes.size()-i-1; ++j){
                    int tempWeight;
                    if(boxes.get(j).getWeight() > boxes.get(j+1).getWeight()){
                        tempWeight = boxes.get(j).getWeight();
                        boxes.get(j).setWeight(boxes.get(j+1).getWeight()); 
                        boxes.get(j+1).setWeight(tempWeight);
                    }
                }
            }
            for (Box box : boxes) {
                System.out.println(box.getWeight());
            }
            return boxes;
        }
        public static void main(String[] args) {
            //Scanner s = new Scanner(System.in);
            
        }
    }

    上面的问题很简单,透过现象看本质就是从小到大一个排序的过程,然后累加。。。还不能很好的体现出贪心的这种感觉,那我们就来一个经典一点的背包问题

    package thinking;
    
    import java.util.Scanner;
    
    import org.junit.Test;
    
    /* QUESTION : A traveler has a backpack of up to Mkg, and now has n items, each weighing W1, W2,...Wn.The value of
     *               each piece are respectively C1, C2,...,Cn.the number of each item if enough. The maxinum value of a 
     *               traveler.
     * */
    
    public class PackageQuestion {
        
        int capacity;
        int n; // 物件的数量
        
        @Test
        public void getMaxValue(){
            
            // 输入物件信息
            System.out.println("please input the capacity of backpack!");
            Scanner sca = new Scanner(System.in);
            capacity = sca.nextInt();
            System.out.println("please input the number of the items!");
            n = sca.nextInt();
            int[] weight = new int[n]; // 重量数组
            int[] value = new int[n];  // 对应的价值数组
            int[] index = new int[n];  // 一个额外的记录变化的数组,后面会进行排序交换,所以每一个物品都要贴一个标签
            System.out.println("please input the weight of these items!");
            for(int i = 0; i<n; ++i){
                weight[i] = sca.nextInt();
            }
            System.out.println("please input the value of these items!");
            for(int i =0; i<n; ++i){
                value[i] = sca.nextInt();
            }
            
            //下面就是重场戏了
            // 因为每个物品的重量和价值都不一样,直观可比性不强,所以我们想要一个可以直观比较的参数,进而想到单位重量下的价值
            double[] ev = new double[n]; // 单位重量下的价值数组
            for(int i = 0; i<n; ++i){
                double v = (double)value[i] / (double)weight[i];
                ev[i] = v;
                index[i] = i; //初始化标志
            }
            // 然后下面就是一个复杂的按照价值的由高到低的排序的过程,采用选择排序或者冒泡都可以。
            for(int i = 0; i<n-1; ++i){
                for(int j = i+1; j<n; ++j){
                    if(ev[i] < ev[j]){// 前面的单位重量下的价值小于后面的,就交换位置
                        double temp;
                        temp = ev[i];
                        ev[i] = ev[j];
                        ev[j] = temp;
                        // 位置的改变后,一定要注意标志位置的也要改变
                        int temp3 = index[i];
                        index[i] = index[j];
                        index[j] = temp3;
                    }
                }
            }
            
            // 用两个新数组来装这个排好序的重量和价值
            int[] wei = new int[n];
            int[] val = new int[n];
            for(int i = 0; i<n; ++i){
                wei[i] = weight[index[i]];
                val[i] = value[index[i]];
            }
            
            //排好序后的监测一下
            System.out.println("weight:");
            for(int i = 0; i<n; ++i){
                System.out.print(wei[i]+"	");
                
            }
            System.out.println("value:");
            for(int i = 0; i<n; ++i){
                
                System.out.print(val[i]+"	");
                
            }
            System.out.println("index:");
            for(int i = 0; i<n; ++i){
            
                System.out.print(index[i]+"	");
            }
            
             //排好序后就开始进行贪心子结构最优化
            int x = 0;
            while(capacity > 0){
                if(wei[0] > capacity){
                    System.out.println("ur backpack is too small, get changed!");
                    System.exit(0);
                }else{
                    if(wei[x] < capacity){
                        System.out.println("get the value is "+val[x]+" item");
                        capacity = capacity-wei[x];
                        x++;
                    }else{
                        System.out.println("ur backpack can't pack any more!");
                        System.exit(0);
                    }
                    
                }
            }
            
        }
        public static void main(String[] args) {
    
        }
    }

    上面这个稍微复杂一些,但还是逃脱不开从最值找的一个步骤,只不过这里的最值稍微做了一点技巧就是求了一个单位最值,从而来提高精准度,并且加上了标志数据的标志,思路也是比较简单的。

  • 相关阅读:
    Java版MD5加密算法
    【Struts2复习知识点四】Path路径问题
    IE7与IE8浏览器下session cookie的共享问题以及区别
    【Struts2复习知识点八】DomaimModel域模型接收参数
    Activity class {package/class} does not exist及Unable to start activity ComponentInfo 解决方法
    【Struts2复习知识点二】namespace的配置
    【Struts2复习知识点五】ActionMethod 动态指定调用方法
    【Struts2复习知识点一】配置struts2环境
    JS面向对象编程
    【Struts2复习知识点三】Action的配置
  • 原文地址:https://www.cnblogs.com/AmoryWang-JavaSunny/p/6504346.html
Copyright © 2011-2022 走看看