贪心算法
贪心算法的定义:选取当前最优策略,最终找到最优解
贪心算法的难点在于,要解决当前最优未必是整体最优的问题
贪心算法之区间覆盖问题
先上题目:
农夫约翰正在分配他的N头(1 <= N <= 25,000)头母牛在谷仓周围做一些清洁工作。他一直想让一头母牛进行清理工作,并将一天分为T班(1 <= T <= 1,000,000),第一个是班1,最后一个是T班。
每头母牛只能在一定间隔内使用。白天进行清洁工作的次数。任何被选定负责清洁工作的母牛将在整个间隔时间内工作。
您的工作是帮助农夫约翰分配一些奶牛到班次,以便(i)每个班次至少分配一头奶牛,并且(ii)尽可能少地母牛参与清洁工作。如果无法为每个班次分配一头母牛,请打印-1。
输入
*第1行:两个以空格分隔的整数:N和T
*第2..N + 1行:每行包含母牛可以工作的时间间隔的开始和结束时间。母牛在开始时间开始工作,在结束时间之后结束。
输出
*第1行:如果无法为每个班次分配一头母牛,农夫约翰需要雇用的最小母牛数或-1。
样本输入
3 10
1 7
3 6
6 10
样本输出
2
暗示
此问题有大量输入数据,请使用scanf()而不是cin读取数据,以避免超过时间限制。
输入详细信息:
有3头母牛和10个班次。#1奶牛可以上班1..7,#2牛可以上班3..6,而#3牛可以上班6..10。
输出详细信息:
通过选择1号和3号奶牛,所有班次都包括在内。没有办法使用少于2头母牛来覆盖所有班次。
这是一道典型的区间覆盖问题,题目的大体意思就是,第一行输入的两个参数为,牛的数量,第二个为总的工作区间。后面依次为每头牛的工作的开始时间和结束时间。要求最少分配几头牛可以覆盖所有工作区间,即可以完成所有工作。
图片上为大致结题思路,代码如下:
package demo;
import java.util.Scanner;
public class 贪心算法之区间覆盖问题 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();// 输入牛的数量
int m = sc.nextInt();// 输入工作总区间
Job[] jb = new Job[n];
// 初始化job数组,否则会报空指针异常
for (int i = 0; i < n; i++) {
jb[i] = new Job(sc.nextInt(), sc.nextInt());
}
int start = 1;
int end = 1;
int count = 1;
for (int i = 0; i < n; i++) {
int left = jb[i].left;
int right = jb[i].right;
if (i == 0 && jb[i].left > start)
break;
if (left <= start) {
end = Math.max(end, right);
} else {
count++;
start = end + 1;
if (left > end) {
break;
} else {
end = Math.max(end, right);
}
}
if (end >= m)
break;
}
if (end >= m) {
System.out.println(count);
} else
System.out.println(-1);
}
private static class Job implements Comparable<Job> {// 要比较每段区间末尾,同时要关联区间开端,就要把区间的两端进行关联,进行封装是比较合适的
int left, right;
public Job(int left, int right) {
this.left = left;
this.right = right;
}
@Override
public int compareTo(Job o) {
// TODO Auto-generated method stub
int x = this.left - o.left;
if (x == 0) {
return this.right - o.right;
} else
return x;
}
}
}