贪心算法

贪心算法其实就是一种分而治之思想的体现。一个大规模的问题,在小规模下达到最优,那么很有可能在整个大规模下也达到最优,但并不绝对。
贪心算法的“贪心”就体现在局部达到最优。
举个可以使用贪心算法的栗子:

/**
     * 贪心算法 找硬币
     *  有 1 2 5 10 20 50 100   7种纸币面额
     *数量3 1 2  1  1  3   5   用最少张找出
     */
    public void coinChange() {
        //人民币面额
        int[] values = {1, 2, 5, 10, 20, 50, 100};
        //各种面值的 数量集合
        int[] counts = {3, 1, 2, 1, 1, 3, 5};

        int need = 442;
        for(int i=values.length-1;i>=0;i--){
            if(need>=values[i] && counts[i]>0){
                System.out.print(values[i]+" ");
                need -= values[i];
                counts[i]--;
                i++;
            }
            if(need == 0){
                break;
            }
        }
    }

使用最少张的纸币,那么局部最优就是每次纸币面额尽量大
在这种情况下使用贪心算法是最优解。
但并一定总是这样,例如下面这个栗子。

/**
     * 贪心算法  背包问题
     *背包容量M = 150   7个物品 重量  35 30 60 50 40 10 25 价值 10 40 30 50 35 40 30
     * 总价值要最大
     */
    public static void packageValue(){
            int m = 150;
            int value = 0;
            int[] weight = {35,30,60,50,40,10,25};
            int[] values = {10,40,30,50,35,40,30};
            Item item1 = new Item(35,10);
            Item item2 = new Item(30,40);
            Item item3 = new Item(60,30);
            Item item4 = new Item(50,50);
            Item item5 = new Item(40,35);
            Item item6 = new Item(10,40);
            Item item7 = new Item(25,30);
            List<Item> items = new ArrayList<>();
            items.add(item1);
            items.add(item2);
            items.add(item3);
            items.add(item4);
            items.add(item5);
            items.add(item6);
            items.add(item7);
            items.sort(null);

            for(int i=items.size()-1;i>=0;i--){
                Item it = items.get(i);
                if(it.getWeight()<m){
                    m -= it.getWeight();
                    value += it.getValue();
                    System.out.println("当前背包容量:"+ m + " 当前总价值:"+ value+" ");
                }
            }

    }

    static class Item implements Comparable{
        int value;
        int weight;
        public Item(int weight,int value){
            this.weight = weight;
            this.value = value;
        }

        public int getValue() {
            return value;
        }

        public void setValue(int value) {
            this.value = value;
        }

        public int getWeight() {
            return weight;
        }

        public void setWeight(int weight) {
            this.weight = weight;
        }

        @Override
        public int compareTo(Object o) {
            Item obj  =(Item) o;
            if(this.value>obj.getValue()){
                return 1;
            }
            else if(this.value<obj.getValue()){
                return -1;
            }
            else{
                if(this.weight<obj.weight){
                    return 1;
                }
                else{
                    return -1;
                }
            }
        }
    }

这个问题的关键在于什么是局部最优,如果仅像代码中这样找到价值最大,很容易就能发现这并不是最优解。那么局部最优应该是什么?重量最小吗?应该是单位价值最高。
所以在使用贪心算法时,一定要考虑什么才算局部最优?
改进后的程序

/**
     * 贪心算法  背包问题
     *背包容量M = 150   7个物品 重量  35 30 60 50 40 10 25 价值 10 40 30 50 35 40 30
     * 总价值要最大
     */
    public static void packageValue(){
            int m = 150;
            int value = 0;
            int[] weight = {35,30,60,50,40,10,25};
            int[] values = {10,40,30,50,35,40,30};
            Item item1 = new Item(35,10);
            Item item2 = new Item(30,40);
            Item item3 = new Item(60,30);
            Item item4 = new Item(50,50);
            Item item5 = new Item(40,35);
            Item item6 = new Item(10,40);
            Item item7 = new Item(25,30);
            List<Item> items = new ArrayList<>();
            items.add(item1);
            items.add(item2);
            items.add(item3);
            items.add(item4);
            items.add(item5);
            items.add(item6);
            items.add(item7);
            items.sort(null);

            for(int i=items.size()-1;i>=0;i--){
                Item it = items.get(i);
                if(it.getWeight()<=m){
                    m -= it.getWeight();
                    value += it.getValue();
                    System.out.println("当前背包容量:"+ m + " 当前总价值:"+ value+" ");
                }
            }

    }

    static class Item implements Comparable{
        int value;
        int weight;
        public Item(int weight,int value){
            this.weight = weight;
            this.value = value;
        }

        public int getValue() {
            return value;
        }

        public void setValue(int value) {
            this.value = value;
        }

        public int getWeight() {
            return weight;
        }

        public void setWeight(int weight) {
            this.weight = weight;
        }

        @Override
        public int compareTo(Object o) {
            Item obj  =(Item) o;
            if((1.0*this.value/this.weight)>(1.0*obj.getValue()/obj.getWeight())){
                return 1;
            }
            else if((1.0*this.value/this.weight)<(1.0*obj.getValue()/obj.getWeight())){
                return -1;
            }
            else{
                return 0;
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值