POJ1328 Radar Installation 貪心
阿新 • • 發佈:2018-05-26
esp 安排 排序 數據 urn clas mat 當前 code
題目大意
給出幾個點的坐標,雷達的覆蓋範圍為R,雷達布置在x軸上,問要覆蓋這些點,至少需要多少雷達?
思路
由點的坐標我們可以得到能控制到該點的區間。由此問題就變成了:給出區間集合\(R\),求一點集\(P\),使得任意區間\([l,r]\in R, \exists p\in P且p\in[l,r]\)。求這點集元素個數的最小值。
貪心不是指做出了當前決策後,當前決策就永遠不變。如果以後改變了一個決策,但是這個決策對之前的結果沒有影響,這仍然成立。
如果我們把所有區間按左端點大小從小到大排序,那麽對於當前區間,我們讓它(以後的區間)盡可能在不影響以前區間的被負責情況下,由負責前幾個區間的點負責它(們)。
為什麽這麽做呢?如果以後的區間全部不由以前的點負責,且知道了安排的最優值:如果以後的區間中存在一個或幾個點,它所負責的區間全部可以由以前的區間所負責,那麽這個點便是多余的;如果是部分可以由以前的點負責,那麽把這些能被以前的點負責的區間由以前的點負責,其余的區間由當前點負責,結果不會變壞。
那麽如何達到這一點呢?我們枚舉每一個區間,並讓最後一個點位於它所負責的區間的盡可能靠右的位置,(令最後一個點負責的區間集為C)也就是\(\min_{[l,r]\in C}\{r\}\)。這樣會使以後的區間被這個點所負責的可能性最大。
為什麽呢?令當前點位置為\(p\)。以後的區間\([l,r]\)不被該點負責的情況為\(l>p\)。如果把這個點靠左一點,不可能的區間就變大了。
註意事項
- 註意\(R<0\)的情況
- 因為有多組數據,讀入文件數據時,如果發現無解,不能提前跳出。
- 坐標題,一律用double,且不要用floor。
#include <cstdio>
#include <cstdarg>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int MAX_RANGE_CNT = 1010, INF = 0x3f3f3f3f;
struct Range
{
double L, R;
Range(double l, double r):L(l), R(r){}
Range() {};
}_ranges[MAX_RANGE_CNT];
int TotRange;
double R;
bool CmpL(Range a, Range b)
{
return a.L < b.L;
}
int main()
{
int caseCnt = 0;
while (scanf("%d%lf", &TotRange, &R) && (TotRange || R))
{
caseCnt++;
int ans = 0;
double pos = -INF;
if (R < 0)
ans = -1;
for (int i = 1; i <= TotRange; i++)
{
double x, y;
scanf("%lf%lf", &x, &y);
if (abs(y) > R)
ans = -1;
else
{
double Len = (sqrt((double)(R * R - y * y)));
_ranges[i] = Range(x - Len, x + Len);
}
}
if(ans != -1)
{
sort(_ranges + 1, _ranges + TotRange + 1, CmpL);
for (int i = 1; i <= TotRange; i++)
{
if (_ranges[i].L > pos)
{
ans++;
pos = _ranges[i].R;
}
else
pos = min(pos, _ranges[i].R);
}
}
printf("Case %d: %d\n", caseCnt, ans);
}
return 0;
}
POJ1328 Radar Installation 貪心