一、题目描述
有 N 头牛在畜栏中吃草。
每个畜栏在同一时间段只能提供给一头牛吃草,所以可能会需要多个畜栏。
给定N头牛和每头牛开始吃草的时间A以及结束吃草的时间B,每头牛在 这一时间段内都会一直吃草。
当两头牛的吃草区间存在交集时(包括端点),这两头牛不能被安排在同一个畜栏吃草。
求需要的最小畜栏数目和每头牛对应的畜栏方案。
输入格式
- 第1行:输入一个整数N。
- 第2…N+1行:第i+1行输入第i头牛的开始吃草时间A以及结束吃草时间B,数之间用空格隔开。
输出格式
- 第1行:输入一个整数,代表所需最小畜栏数。
- 第2…N+1行:第i+1行输入第i头牛被安排到的畜栏编号,编号是从1开始的 连续 整数,只要方案合法即可。
数据范围
输入样例:
5
1 10
2 4
3 6
5 8
4 7
输出样例:
4
1
2
3
2
4
二、题解
方法一:排序 + 小根堆
- 对每头牛
cows[i]
按照吃草的开始时间cows[i].begin
升序排列。 - 尽量往同一个畜栏中放牛,但在某个畜栏加入牛前要判断当前
cur.end
是否严格小于cows[i].begin
- 是,则可放。
- 否则,不可放。
错误:可能是存在排序错误,导致输出错误。
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
BufferedWriter w = new BufferedWriter(new OutputStreamWriter(System.out));
int N = sc.nextInt();
Node[] cows = new Node[N];
for (int i = 0; i < N; i++) {
cows[i] = new Node(sc.nextInt(), sc.nextInt());
cows[i].id = i;
}
Arrays.sort(cows);
Queue<Node> pq = new PriorityQueue<>();
pq.add(cows[0]);
int[] slot = new int[N];
int num = 1;
slot[cows[0].id] = num;
for (int i = 1; i < N; i++) {
Node cur = pq.peek();
if (cur.end < cows[i].begin) {
pq.poll();
pq.add(cows[i]);
slot[cows[i].id] = slot[cur.id];
} else {
num++;
slot[cows[i].id] = num;
pq.add(cows[i]);
}
}
w.write(num + "\n");
for (int i = 0; i < N; i++) {
w.write(slot[i] + "\n");
}
w.flush();
}
static class Node implements Comparable<Node>{
int begin, end, id;
public Node(int _begin, int _end) {
this.begin = _begin;
this.end = _end;
}
@Override
public int compareTo(Node other) {
if (this.begin == other.begin)
return this.end - other.end;
return this.begin - other.begin;
}
}
}
复杂度分析
- 时间复杂度: ,
- 空间复杂度: ,