贪心算法是一种递推算法,用局部最优解来推导全局最优解,是对遍历解空间的一优化。 贪心是动态规划的特例。
1. 区间调度问题
有n项工作,每项工作分别在si时间开始,ti时间结束。
对于每一项工作,你都可以选择是否参与,如果参与,那么自始至终必须全程参与,直到结束。
此外,参与工作的时间段不能够重复,即使是开始和结束的瞬间重叠也不可以。
你的目标是参与尽可能多的工作,那么最多能参与多少工作呢?
正确的策略:每次都选结束时间最早的。
首先对集合排序:结束时间最早的放在前面。
2. 区间选点问题
原始问题:
数轴上有n个闭区间[a_i,b_i]。请选择尽量少的点,使得每个区间内都至少有一个你选择的点。
思路: 因为要选择最少的点,也就是说每次选取的店都应该尽可能的覆盖最多的区间。
那么如果这个点选在某个区间中和选在这个区间的末尾,那肯定选择选在末尾,因为有可能会选到更多的区间,前提是这些区间要按照右端点的值进行排序。
数轴上有n个开区间(ai,bi),选择尽量多个区间,使得这些区间两两没有公共点。
样例输入;
5
1,4
5,6
3,4
6,7
4,5
样例输出:
1,4
4,5
5,6
6,7
import java.util.Scanner;
import java.util.ArrayList;
import java.util.Collections;
class Node implements Comparable<Node>{
int x;
int y;
public Node(int x,int y){
this.x=x;
this.y=y;
}
public int compareTo(Node node) {
if(this.y>node.y)
return 1;
else if(this.y<node.y)
return -1;
else
return 0;
}
}
public class Main {
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
while(scanner.hasNext())
{
int n=scanner.nextInt();
ArrayList<Node> list=new ArrayList<Node>();
scanner.nextLine();
for(int i=0;i<n;i++){
String s=scanner.nextLine();
String[] arr=s.split(",");
Node node=new Node(Integer.parseInt(arr[0]),Integer.parseInt(arr[1]));
list.add(node);
}
Collections.sort(list);
ArrayList<Node> result=new ArrayList<Node>();
Node node=list.get(0);
int y=node.y;
result.add(node);
for(int i=1;i<n;i++){
Node temp=list.get(i);
if(temp.x>=y){
result.add(temp);
y=temp.y;
}
}
for(Node res:result){
System.out.println(res.x+","+res.y);
}
}
scanner.close();
}
}
数轴上有n个闭区间[ai,bi],取尽量少的点,使得每个区间内都至少有一个点。
样例输入:
5
1,4
5,6
3,4
6,7
4,5
样例输出:
4 6
import java.util.Scanner;
import java.util.ArrayList;
import java.util.Collections;
class Node implements Comparable<Node>{
int x;
int y;
public Node(int x,int y){
this.x=x;
this.y=y;
}
public int compareTo(Node node) {
if(this.y>node.y)
return 1;
else if(this.y<node.y)
return -1;
else if(this.x>node.x)
return -1;
else if(this.x<node.x)
return 1;
else
return 0;
}
}
public class Main {
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
while(scanner.hasNext())
{
int n=scanner.nextInt();
ArrayList<Node> list=new ArrayList<Node>();
scanner.nextLine();
for(int i=0;i<n;i++){
String s=scanner.nextLine();
String[] arr=s.split(",");
Node node=new Node(Integer.parseInt(arr[0]),Integer.parseInt(arr[1]));
list.add(node);
}
Collections.sort(list);
ArrayList<Integer> result=new ArrayList<Integer>();
Node node=list.get(0);
int y=node.y;
result.add(y);
for(int i=1;i<n;i++){
Node temp=list.get(i);
if(temp.x>y){
y=temp.y;
result.add(y);
}
}
StringBuffer str=new StringBuffer();
for(int i:result){
str.append(i+" ");
}
System.out.println(str.substring(0,str.length()-1));
}
scanner.close();
}
}
3. 区间覆盖问题
原始问题:
给顶一段线段,若干段区间,问最少多少段区间覆盖