Grade 11 · The greedy methodCitește în română
Covering a segment with the minimum number of intervals
Original: Acoperirea unui segment cu număr minim de intervale
The idea
We want to cover the segment [A, B] using as few as possible of the n given intervals [s[i], f[i]]. We sort the intervals by their left end. We keep the point 'covered up to' (initially A). Among the intervals that start no later than this point, we choose the one that reaches furthest to the right, then move the point to its end. If no interval takes us further, covering is impossible. The number of intervals and their indices are printed, or 'Imposibil' (impossible).
Original description (Romanian)
Vrem să acoperim segmentul [A, B] folosind cât mai puține dintre cele n intervale date [s[i], f[i]]. Sortăm intervalele după capătul stâng. Ținem punctul „acoperit până la” (inițial A). Dintre intervalele care încep cel târziu în acest punct îl alegem pe cel care ajunge cel mai departe la dreapta, apoi mutăm punctul la capătul lui. Dacă niciun interval nu ne duce mai departe, acoperirea e imposibilă. Se afișează numărul de intervale și numerele lor de ordine, sau „Imposibil”.
- Complexity
- O(n log n)
- Grade
- Grade 11 (Clasa a XI-a)
- Chapter
- The greedy method
Examples
Input
0 10 5 0 4 2 6 3 8 5 10 7 9
Expected output
3 1 3 4
Input
0 5 2 1 3 2 5
Expected output
Imposibil
The code
Comments are in Romanian, as in the original collection. Edit freely: you can reset at any time.
/*
* Titlu: Acoperirea unui segment cu număr minim de intervale
* Clasa: 11
* Capitol: Metoda greedy
* Descriere: Vrem să acoperim segmentul [A, B] folosind cât mai puține dintre cele n
* intervale date [s[i], f[i]]. Sortăm intervalele după capătul stâng. Ținem
* punctul „acoperit până la” (inițial A). Dintre intervalele care încep cel
* târziu în acest punct îl alegem pe cel care ajunge cel mai departe la
* dreapta, apoi mutăm punctul la capătul lui. Dacă niciun interval nu ne
* duce mai departe, acoperirea e imposibilă. Se afișează numărul de
* intervale și numerele lor de ordine, sau „Imposibil”.
* Complexitate: O(n log n)
*
* Exemplu
* Intrare:
* 0 10
* 5
* 0 4
* 2 6
* 3 8
* 5 10
* 7 9
* Ieșire:
* 3
* 1 3 4
*
* Exemplu
* Intrare:
* 0 5
* 2
* 1 3
* 2 5
* Ieșire: Imposibil
*/
#include <iostream>
#include <algorithm>
using namespace std;
struct interval
{
int st, dr, nr;
};
interval a[1000];
bool dupaStart(const interval &x, const interval &y)
{
if (x.st != y.st)
{
return x.st < y.st;
}
return x.nr < y.nr;
}
int main()
{
int A, B, n;
cin >> A >> B >> n;
for (int i = 0; i < n; i++)
{
cin >> a[i].st >> a[i].dr;
a[i].nr = i + 1;
}
sort(a, a + n, dupaStart);
int ales[1000], cate = 0;
int acoperit = A, i = 0;
bool posibil = true;
while (acoperit < B)
{
int celMaiDeparte = acoperit, care = -1;
while (i < n && a[i].st <= acoperit)
{
if (a[i].dr > celMaiDeparte)
{
celMaiDeparte = a[i].dr;
care = a[i].nr;
}
i++;
}
if (care == -1)
{
posibil = false;
break;
}
ales[cate++] = care;
acoperit = celMaiDeparte;
}
if (!posibil)
{
cout << "Imposibil\n";
return 0;
}
cout << cate << '\n';
for (int j = 0; j < cate; j++)
{
cout << ales[j] << ' ';
}
cout << '\n';
return 0;
}
Runs on a real g++ (C++17, -O2) through Compiler Explorer. Keep runs short; there's a time limit.