题解:AcWing 907 区间覆盖
【算法来源】
AcWing:907. 区间覆盖 - AcWing题库
【题目描述】
给定 \(N\) 个区间 \([a_i,b_i]\) 以及一个区间 \([s,t]\),请你选择尽量少的区间,将指定区间完全覆盖。
输出最少区间数,如果无法完全覆盖则输出 \(-1\)。
【输入】
第一行包含两个整数 \(s\) 和 \(t\),表示给定区间的两个端点。
第二行包含整数 \(M\),表示给定区间数。
接下来 \(N\) 行,每行包含两个整数 \(a_i,b_i\),表示一个区间的两个端点。
【输出】
输出一个整数,表示所需最少区间数。
如果无解,则输出 \(-1\)。
【输入样例】
1 5
3
-1 3
2 4
3 5
【输出样例】
2
【算法标签】
《AcWing 907 区间覆盖》 #贪心#
【代码详解】
#include <bits/stdc++.h>
using namespace std;
const int N = 100005; // 定义最大区间数量
int n; // 区间数量
// 定义区间结构体
struct Range
{
int l, r; // 区间的左右端点
// 重载小于运算符,用于排序
bool operator< (const Range &W) const
{
return l < W.l; // 按照区间的左端点升序排序
}
}range[N]; // 定义区间数组
int main()
{
int st, ed; // 目标区间的左右端点
cin >> st >> ed; // 输入目标区间
cin >> n; // 输入区间数量
// 输入每个区间的左右端点
for (int i=0; i<n; i++)
{
int l, r;
cin >> l >> r;
range[i] = {l, r}; // 将区间存入数组
}
sort(range, range+n); // 按照区间的左端点进行排序
int res = 0; // 记录选择的区间数量
bool success = false; // 标记是否成功覆盖目标区间
// 遍历所有区间
for (int i=0; i<n; i++)
{
int j = i, r = -2e9; // j 用于遍历区间,r 记录当前能覆盖的最远右端点
// 找到所有左端点小于等于 st 的区间,并选择右端点最大的区间
while (j < n && range[j].l <= st)
{
r = max(r, range[j].r); // 更新 r 为最大的右端点
j++;
}
// 如果 r < st,说明无法覆盖 st,直接退出
if (r < st)
{
res = -1; // 无法覆盖,标记为失败
break;
}
res++; // 选择一个区间
if (r >= ed) // 如果当前区间已经覆盖了 ed,标记成功并退出
{
success = true;
break;
}
st = r; // 更新 st 为当前区间的右端点
i = j - 1; // 跳过已经处理过的区间
}
// 如果最终没有覆盖 ed,标记为失败
if (!success) res = -1;
cout << res << endl; // 输出结果
return 0;
}
【运行结果】
1 5
3
-1 3
2 4
3 5
2
浙公网安备 33010602011771号