贪心法解决区间调度(不相交区间和区间选点)问题

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

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

例样输入:
5
1 2 4 6 8
3 5 7 9 10

输出:
3

解题思路:
利用贪心法每一步选取最优的方案,已达到整体最优。想要尽可能参与多个工作,当完成一个工作后就要选取工作结束时间尽可能小的工作,并且下一个工作的开始时间一定要大于现在工作的结束时间。我们可以建立一个对象,将工作的开始时间和结束时间包含进对象中。然后将对象按照结束时间进行排序。然后按照排序后的结果依次选取工作,同时判断是否满足上一个工作的结束时间小于下一个工作的开始时间。

代码如下;

import java.util.*;

public class 不相交区间 {
	private static  class job implements Comparable<job>{
		public int s;
		public int t;
		job(int s, int t){
			this.s = s;
			this.t = t;
		}
		@Override
		public int compareTo(job other) {
			return this.t - other.t;
		}
	}
	
	public static void main(String[] args){
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();
		int[] s = new int[n];
		int[] t = new int[n];
		for(int i=0; i<n; i++){
			s[i] = scanner.nextInt();
		}
		for(int i=0; i<n; i++){
			t[i] = scanner.nextInt();
		}
		job[] arr = new job[n];
		for(int i=0; i<n; i++){
			arr[i] = new job(s[i], t[i]);
		}
		Arrays.sort(arr);
		System.out.println(f(arr, n));
	}

	private static int f(job[] arr, int n) {
		int count = 1;
		int y = arr[0].t;//表示当前工作的结束时间
		for(int i=1; i<n; i++){
			if(arr[i].s>y){
				y = arr[i].t;
				count++;
			}
		}
		return count;
	}
	
}


区间选点问题:
问题描述:
给定多个区间,区间之间可能会发生部分重叠。在一个区间的范围内取一个点则这个区间就被称为被命中区间。要使得所有的区间都成为命中区间;问最少需要取多少个点?假定所有区间都是开区间。

输入:
第一行:n
第二行:n个整数空格隔开,代表n个区间的开始点
第三行:n个整数空格隔开,代表n个区间的结束点

输出:
一个整数,表示需要最少点的个数。

解题思路:
这个解题方法和区间调度的方法完全相同。首先将多出的区间按照先结束的排在前面进行排序。然后将排序后的区间一次取点,第一个区间直接去区间的结束点,之后的每一个区间取点之前都判断一下上一个取点是否在区间内。在则跳过此区间,不在则取这个区间的结束点。直到遍历完所有区间。总之取的每一个点都是区间的结束点。这样能保证发生覆盖的区间只取了一个点。

代码和上面相同。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逍遥自在”

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值