贪心算法----区间调度问题

题目:

  有n项工作,每项工作分别在si时间开始,在ti时间结束。对于每项工作,你都可以选择参与与否。如果选择了参与,那么自始至终都必须全程参与。此外,参与工作的时间段不能重复(即使是开始的瞬间和结束的瞬间的重叠也是不允许的)。你的目标是参与尽可能多的工作,那么最多能参与多少项工作呢?  1≤n≤100000  1≤si≤ti≤109。这道题目还可以称作不相交区间问题。

输入:

  第一行:n
  第二行:n个整数空格隔开,代表n个工作的开始时间
  第三行:n个整数空格隔开,代表n个工作的结束时间

样例输入:

5
1 2 4 6 8
3 5 7 9 10

样例输出:

3
说明:选取工作1,3,5。

思路分析:

  对于这种区间型问题,最好画一个数轴图来直观的看这个问题。

    

  对这个问题,如果使用贪心算法的话,可能有以下几种考虑:

    (1)、每次选取开始时间最早的;

    (2)、每次选取结束时间最早的;

    (3)、每次选取用时最短的;

    (4)、在可选工作中,每次选取与最小可选工作有重叠的部分;

  对于上面的四种算法,只有算法(2)是正确的,其它的三种都可以找到相应的反例,举几个例子就很容易发现反例。在编码的过程中要注意一个问题:我们需要对所有的结束时间进行排序,然后选择出没有被这个区间覆盖的而且开始时间大于这个区间的结束时间的下一个区间,其中涉及到了排序但是排完序之后原来的开始时间和结束时间有可能会被打乱,这里用到了Java的面向对象的封装思想。

代码:

import java.util.Arrays;
import java.util.Scanner;

public class 区间调度问题 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] s = new int[n];
        int[] t = new int[n];
        Job[] jobs = new Job[n];
        for (int i = 0; i < n; i++) {
            s[i] = sc.nextInt();
        }
        for (int i = 0; i < n; i++) {
            t[i] = sc.nextInt();
        }
        for (int i = 0; i < n; i++) {
            jobs[i] = new Job(s[i], t[i]);
        }

        Arrays.sort(jobs);  // 排序这种类型数据必须自定义比较规则
        int res = f(n, jobs);
        System.out.println(res);
    }

    private static int f(int n, Job[] jobs) {
        int cnt = 1;
        int y = jobs[0].t;
        for (int i = 0; i < n; i++) {
            if (jobs[i].s > y) {
                cnt++;
                y = jobs[i].t;
            }
        }
        return cnt;
    }

    private static class Job implements Comparable<Job> {
        int s;
        int t;

        public Job(int s, int t) {
            this.s = s;
            this.t = t;
        }

        @Override
        public int compareTo(Job other) {
            int x = this.t - other.t;
            if (x == 0)
                return this.s - other.s;
            else
                return x;
        }
    }
}

结果:

  

原文地址:https://www.cnblogs.com/xiaoyh/p/10356534.html

时间: 2024-10-11 02:12:05

贪心算法----区间调度问题的相关文章

贪心算法-区间调度问题解之证明

一.贪心算法 定义:一个算法是贪心算法,如果它是通过一些小的步骤来一个求解,并且在每一步根据局部情况选择一个决定,使得某些主要的指标得到优化. 二.区间调度问题 1. 问题:我们有一组需求{1,2,3,......,N},第i个需求与一个开始时间s(i),结束时间f(i)相对应.如果没有两个需求在时间上重叠,我们就说需求的子集是相容的. 2. 目标:寻找一个最大的相容子集O. 3. 算法: 初始令R是所有需求的集合,设A为空 While ( |R| > 0 ) 选择一个最早结束的需求 把i加入到

贪心:区间调度问题

*/--> pre.src {background-color: Black; color: White;} 贪心:区间调度问题 有 n 项工作,每项工作分别在 si 时间开始,在 ti 时间结束.对于每项工作,你都可以选择参与与否.参与工作的时间段不能重复 (开始的瞬间和结束的瞬间重叠也是不允许的) 分析:在可选的工作中,每次都选取结束时间最早的工作 // CreateTime: 2015-04-07 21:45:48 #include <iostream> #include <

编程算法 - 区间调度问题 代码(C)

区间调度问题 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 有n项工作, 每项工作分别在s时间开始, 在t时间结束. 对于每项工作可以选择参与与否, 如果参与, 则全程参与. 参与时间段不能重叠, 包括起始结束瞬间也不能重叠. 求最多能参与多少项工作? 使用贪心法, 策略是在可选工作中, 每次都选取结束时间最早的工作. 代码: /* * main.cpp * * Created on: 2014.7.17 * Author: spike

贪心算法----区间覆盖问题(POJ2376)

题目: 题目的大概意思是约翰这个农民有N条牛,这些牛可以在一天中的某个时间段可以进行工作,他想把这个时间段分成若干个片段让这些牛去进行打扫任务,你的任务是安排尽量少的牛然后可以完成分成这些片段的打扫任务. 输入: 第一行两个数,第一个数代表牛的个数N,第二个数代表时间T,表示的是时间段[1,T]. 下面的N行每行表示牛工作的时间段. 输出: 输出使用最少的牛的数量. 思路分析:这道题目完全就是一个区间覆盖问题的裸题,求解过程,将每个牛工作的区间按左端点递增排序,如果左端点相同,按右端点递增顺序排

贪心算法-----单线程:活动安排问题 多线程:多机调度问题

一.贪心算法的特点 顾名思义,贪心算法总是做出在当前看来是最好的选择.虽然贪心算法并不从整体最优上加以考虑,它所做出的选择只是在某种意义上的局部最优选择. 贪心算法的优点是更简单,更直接且解题效率更高,即使贪心算法不能得到整体最优解,但其最终结果却是最优解的很好的近似解. 二.贪心算法的理解 由于涉及到在做出在当前看来最好的选择,所以会经常采用排序算法,推荐使用快速排序算法,复杂度是O(nlgn),且在同等复杂度算法中效率是最高的, 本文涉及的排序都采用冒泡排序,只是注明需要排序而已. 贪心算法

贪心算法选择不相交区间

Input 输入数据包含多个测试实例,每个测试实例的第一行只有一个整数n(n<=100),表示你喜欢看的节目的总数,然后是n行数据,每行包括两个数据Ti_s,Ti_e (1<=i<=n),分别表示第i个节目的开始和结束时间,为了简化问题,每个时间都用一个正整数表示.n=0表示输入结束,不做处理. Output 对于每个测试实例,输出能完整看到的电视节目的个数,每个测试实例的输出占一行. Sample Input 12 1 3 3 4 0 7 3 8 15 19 15 20 10 15 8

贪心算法设计 关于区间选择问题

/* 现在有n项工作,知道每一项工作的开始时间和结束时间,问最多可以选择多少工作 算法设计:贪心算法,不断选择不冲突的那些结束时间最短的工作 */ #include<iostream> #include<vector> #define max_n 100001 using namespace std; int N; //first is the start of the job,and the secone is the end time of the job typedef pa

算法导论 第十六章:贪心算法之单任务调度问题

贪心算法是使所做的选择看起来都是当前最优的,通过所做的局部最优选择来产生一个全局最优解. 其具有的性质如下: 1)贪心选择性质:一个全局最优解可以通过局部最优(贪心)选择来达到.即,在考虑如何做选择时,我们只考虑对当前问题最佳的选择而不考虑子问题的结果. 这一点是贪心算法不同于动态规划之处:在动态规划中,每一步都要做出选择,但是这些选择依赖于子问题的解.因此,解动态规划问题一般是自底向上,从小问题处理至大问题.在贪心算法中,我们所做的总是当前看似最优的选择,然后再解决选择之后所出现的子问题.贪心

区间调度问题

1. 相关定义 在数学里,区间通常是指这样的一类实数集合:如果x和y是两个在集合里的数,那么,任何x和y之间的数也属于该集合.区间有开闭之分,例如(1,2)和[1,2]的表示范围不同,后者包含整数1和2. 在程序世界,区间的概念和数学里没有区别,但是往往有具体的含义,例如时间区间,工资区间或者音乐中音符的开始结束区间等,图一给出了一个时间区间的例子.区间有了具体的含义之后,开闭的概念就显得非常重要,例如时间区间[8:30,9:30]和[9:30,10:30]两个区间是有重叠的,但是[8:30,9