zoukankan      html  css  js  c++  java
  • 贪心算法----区间覆盖问题(POJ2376)

    题目:

      

      题目的大概意思是约翰这个农民有N条牛,这些牛可以在一天中的某个时间段可以进行工作,他想把这个时间段分成若干个片段让这些牛去进行打扫任务,你的任务是安排尽量少的牛然后可以完成分成这些片段的打扫任务。

      输入:

        第一行两个数,第一个数代表牛的个数N,第二个数代表时间T,表示的是时间段[1,T]。

        下面的N行每行表示牛工作的时间段。

      输出:

        输出使用最少的牛的数量。

      思路分析:这道题目完全就是一个区间覆盖问题的裸题,求解过程,将每个牛工作的区间按左端点递增排序,如果左端点相同,按右端点递增顺序排列。设置start变量初始化为时间段的左端点,在这些区间中找到满足左端点小于start并且右端点尽量往右靠的区间,然后将这个区间的右端点设置为end变量,这样就找到了一个区间,然后将start变量更新为end变量,然后再在剩下的区间继续寻找左端点小于start并且右端点尽量往右靠的区间,然后再将这个区间的右端点设置为end变量,这样就又找到了一个区间,如此循环下去,直到end大于时间段的右端点,退出循环,这样就能找出使用哪些区间能够覆盖这个时间段了。解答这道题目在循环中使用一个变量计数即可。

      贪心思想:要求用最少的区间进行覆盖,那么选取的区间必然要尽量长,而已覆盖到的区域之前的地方已经不用考虑了,可以理解成所有可覆盖的左端点都已被覆盖了,那么能够使得区间更长的取决于右端点,左端点没有太大的意义,所以选择右端点来覆盖。而且在循环的过程中,相当于很多的子问题最优组成了全局的最优。找到每个能够使用的最长区间就相当于子问题最优,而每个子问题最优就构成了使用的区间数最少这个全局最优。

      代码:

     1 import java.util.Arrays;
     2 import java.util.Scanner;
     3 
     4 public class 区间覆盖问题 {
     5     public static void main(String[] args) {
     6         Scanner sc = new Scanner(System.in);
     7         int N = sc.nextInt();
     8         int T = sc.nextInt();
     9         Job[] jobs = new Job[N];
    10         for (int i = 0; i < N; i++) {
    11             jobs[i] = new Job(sc.nextInt(), sc.nextInt());
    12         }
    13         Arrays.sort(jobs);
    14         int start = 1;// 要覆盖的目标点,end覆盖该点的所有区间中右端点最右
    15         int end = 1;
    16         int ans = 1;
    17         for (int i = 0; i < N; i++) {
    18 
    19             int s = jobs[i].s;
    20             int t = jobs[i].t;
    21 
    22             if (i == 0 && s > 1)
    23                 break;
    24 
    25             if (s <= start) {// 当前区间有可能覆盖start
    26                 end = Math.max(t, end);// 更新更右的端点
    27             } else {// 开始下一个区间
    28                 ans++;// 上一个目标覆盖已经达成,计数加1
    29                 start = end + 1;// 更新起点,设置一个新的覆盖目标
    30                 if (s <= start) {
    31                     end = Math.max(t, end);
    32                 } else {
    33                     break;
    34                 }
    35             }
    36             if (end >= T) {// 当前的end超越了线段的右侧
    37                 break;
    38             }
    39 
    40         }
    41         if (end < T)
    42             System.out.println(-1);
    43         else
    44             System.out.println(ans);
    45     }
    46 
    47     private static class Job implements Comparable<Job> {
    48         int s;
    49         int t;
    50 
    51         public Job(int s, int t) {
    52             this.s = s;
    53             this.t = t;
    54         }
    55 
    56         /** 按照区间起点排序 */
    57         @Override
    58         public int compareTo(Job other) {
    59             int x = this.s - other.s;
    60             if (x == 0)
    61                 return this.t - other.t;
    62             else
    63                 return x;
    64         }
    65     }
    66 }

      结果:

        

  • 相关阅读:
    使用tcmalloc编译启动时宕机
    使用tcmalloc编译出现undefined reference to `sem_init'
    使用AddressSanitizer做内存分析(一)——入门篇
    VIM-美化你的标签栏
    Entity Framework Code First (六)存储过程
    Entity Framework Code First (五)Fluent API
    Entity Framework Code First (四)Fluent API
    Entity Framework Code First (三)Data Annotations
    Entity Framework Code First (二)Custom Conventions
    Entity Framework Code First (一)Conventions
  • 原文地址:https://www.cnblogs.com/xiaoyh/p/10364579.html
Copyright © 2011-2022 走看看