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

这篇博客介绍了一个使用Java解决区间覆盖问题的贪心算法。通过将牛的工作时间段按左端点升序排序,然后依次选择覆盖尽可能多区域的区间,从而找到使用最少的牛完成所有时间段的方法。代码实现中,博主给出了详细步骤和逻辑解释。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

4d08ebdc0361df3b59cb75426f890f5e.png

题目的大概意思是约翰这个农民有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 {

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 }

结果:

9409d61ddf82146edc6808890eccb830.png

作者:|旧市拾荒|

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值