贪心算法-活动选择问题&背包问题

目录

活动选择问题

[无重叠区间-Leetcode 435](#无重叠区间-Leetcode 435)

分数背包问题--贪心解法

贪心法

[0-1 背包问题](#0-1 背包问题)

贪心法

贪心算法的局限

[Set cover problem](#Set cover problem)


活动选择问题

分析:

复制代码
/*
要在一个会议室举办n个活动
- 每个活动有它们各自的起始和结束时间
- 找出在时间上互不冲突的活动组合,能够最充分利用会议室(举办的活动次数最多)

例1
    0   1   2   3   4   5   6   7   8   9
        |--------)              
            |--------)
                 |--------)

 选1 3 能够举办2个活动

例2
    0   1   2   3   4   5   6   7   8   9
        |---)
                |---)
    |-----------------------)
                        |-------)
                                    |---)
                        |---------------)

  4个活动


  几种贪心策略
  1.优先选择持续时间最短的活动 以下情形不满足方案out
        0   1   2   3   4   5   6   7   8   9
            |---------------)
                        |-------)
                            |----------------)\
  2.优先选择冲突最少的活动
  编号 0  1   2   3   4   5   6   7   8   9
  1   |-------)                               3  选中
  2       |-------)                           4
  3       |-------)                           4
  4       |-------)                           4
  5           |-------)                       4
  6               |-------)                   2  选中
  7                   |------------)          4
  8                            |--------)     4
  9                            |--------)      4
  10                           |--------)      4
  11                               |-------)   3  选中

    但实际上应该是1 5 7 11 所以这个也不行

    3. 优先选择最先开始的活动 不行
        0   1   2   3   4   5   6   7   8   9
        |-----------------------------------)
            |---)
                |---)
                    |---)

    4. 优先选择最先结束的活动

 */
java 复制代码
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

/**
 * <h1>活动选择问题 - 贪心解法</h1>
 * Leetcode 435 无重叠区间本质就是活动选择问题
 */
public class ActivitySelectionProblem {
    static class Activity{
        int index;
        int start;
        int finish;

        public Activity(int index,int start,int finish){
            this.index = index;
            this.start = start;
            this.finish = finish;
        }
        public int getFinish(){
            return finish;
        }

        @Override
        public String toString(){
            return "Activity("+index+")";
        }
    }

    public static void main(String[] args) {
        Activity[] activities = new Activity[]{
                new Activity(0, 1, 3),
                new Activity(1, 2, 4),
                new Activity(2, 3, 5)
        };
//        Activity[] activities = new Activity[]{
//                new Activity(0, 1, 2),
//                new Activity(1, 3, 4),
//                new Activity(2, 0, 6),
//                new Activity(3, 5, 7),
//                new Activity(4, 8, 9),
//                new Activity(5, 5, 9)
//        };
        Arrays.sort(activities, Comparator.comparingInt(Activity::getFinish));
        System.out.println(Arrays.toString(activities));
        select(activities, activities.length);
    }

    public static void select(Activity[] activities, int length) {
        List<Activity>result = new ArrayList<>();
        Activity prev = activities[0];
        result.add(prev);
        for(int i = 1;i<length;i++){
            Activity curr = activities[i]; //当前正在处理的活动
            if (curr.start >= prev.finish) {
                result.add(curr);
                prev = curr;
            }
        }
        for (Activity activity : result) {
            System.out.println(activity);
        }
    }
}

435. 无重叠区间 - 力扣(LeetCode)

无重叠区间-Leetcode 435
题目编号 题目标题 算法思路
435 无重叠区间 贪心
java 复制代码
class Solution {
    public int eraseOverlapIntervals(int[][] intervals) {
        if(intervals.length==0){
            return 0;
        }
        Arrays.sort(intervals,Comparator.comparingInt(a->a[1]));
        int i,j;
        i=0;
        int count =1;
        for(j = 1;j<intervals.length;j++){
            if(intervals[j][0] >= intervals[i][1]){
                i = j;
                count++;
            }
        }
        return intervals.length-count;
    }
}
  • 找到不重叠的最多的活动数(count),即活动选择问题原始需求

  • 在此基础上,活动总数 - count,就是题目要的排除数量

分数背包问题--贪心解法

贪心法
复制代码
/*
1. n个物品都是液体,有重量和价值
2. 现在你要取走 10升 的液体
3. 每次可以不拿,全拿,或拿一部分,问最高价值是多少

    编号 重量(升) 价值
    0   4       24      水
    1   8       160     牛奶       选中 7/8
    2   2       4000    五粮液     选中
    3   6       108     可乐
    4   1       4000    茅台       选中

    8140

    简化起见,给出的数据都是【价值/重量】能够整除,避免计算结果中出现小数,增加心算难度
 */
java 复制代码
import java.util.Arrays;
import java.util.Comparator;

public class FractionalKnapsackProblem {

    static class Item {
        int index;
        int weight;
        int value;

        public Item(int index, int weight, int value) {
            this.index = index;
            this.weight = weight;
            this.value = value;
        }

        public int unitPrice() {
            return value / weight;
        }

        @Override
        public String toString() {
            return "Item(" + index + ")";
        }
    }

    public static void main(String[] args) {
        Item[] items = new Item[]{
                new Item(0, 4, 24),
                new Item(1, 8, 160),
                new Item(2, 2, 4000),
                new Item(3, 6, 108),
                new Item(4, 1, 4000),
        };
        select(items, 10);
    }

    static void select(Item[] items, int total) {
        Arrays.sort(items, Comparator.comparingInt(Item::unitPrice).reversed());
        //reversed()降序
        int remainder = total;
        int max = 0;
        for (Item item : items) {
            if (remainder - item.weight >= 0) {//一次能够拿完
                max += item.value;
                remainder -= item.weight;
            } else {//拿不完
                max += remainder * item.unitPrice();
                break;
            }
        }
        System.out.println("最高价值为:" + max);
    }


}

0-1 背包问题

贪心法

可能得不到最优解

复制代码
 /*
    0-1 背包问题

    1. n个物品都是固体,有重量和价值
    2. 现在你要取走不超过 10克 的物品
    3. 每次可以不拿或全拿,问最高价值是多少

        编号 重量(g)  价值(元)
        0   1       1_000_000      钻戒一枚        选中
        1   4       1600           黄金一块        400
        2   8       2400           红宝石戒指一枚   300
        3   5       30             白银一块

按照分数背包问题解法: 1001630 但其实不对  应该是1002400
     */
java 复制代码
import java.util.Arrays;
import java.util.Comparator;

public class KnapsackProblem {
   

    static class Item {
        int index;
        int weight;
        int value;

        public Item(int index, int weight, int value) {
            this.index = index;
            this.weight = weight;
            this.value = value;
        }

        public int unitValue() {
            return value / weight;
        }

        @Override
        public String toString() {
            return "Item(" + index + ")";
        }
    }

    public static void main(String[] args) {
        Item[] items = new Item[]{
                new Item(0, 1, 1_000_000),
                new Item(1, 4, 1600),
                new Item(2, 8, 2400),
                new Item(3, 5, 30)
        };
        select(items, 10);
    }

    static void select(Item[] items, int total) {
        Arrays.sort(items, Comparator.comparingInt(Item::unitValue).reversed());
        int max = 0; // 最大价值
        for (Item item : items) {
            System.out.println(item);
            if (total >= item.weight) { // 可以拿完
                total -= item.weight;
                max += item.value;
            } else { // 拿不完
//                max += total * item.unitValue();
//                break;
            }
        }
        System.out.println("最大价值是:" + max);
    }
}

贪心算法的局限

问题名称 是否能用贪心得到最优解 替换解法
Dijkstra(不存在负边) ✔️
Dijkstra(存在负边) Bellman-Ford
Prim ✔️
Kruskal ✔️
零钱兑换 动态规划
Huffman 树 ✔️
活动选择问题 ✔️
分数背包问题 ✔️
0-1 背包问题 动态规划

Set cover problem

集合覆盖问题

这个问题后面会出文章! 敬请期待!

相关推荐
Swift社区2 小时前
在 Swift 中实现字符串分割问题:以字典中的单词构造句子
开发语言·ios·swift
没头脑的ht2 小时前
Swift内存访问冲突
开发语言·ios·swift
没头脑的ht2 小时前
Swift闭包的本质
开发语言·ios·swift
wjs20242 小时前
Swift 数组
开发语言
吾日三省吾码3 小时前
JVM 性能调优
java
stm 学习ing3 小时前
FPGA 第十讲 避免latch的产生
c语言·开发语言·单片机·嵌入式硬件·fpga开发·fpga
湫ccc4 小时前
《Python基础》之字符串格式化输出
开发语言·python
弗拉唐4 小时前
springBoot,mp,ssm整合案例
java·spring boot·mybatis
oi774 小时前
使用itextpdf进行pdf模版填充中文文本时部分字不显示问题
java·服务器