題意:
一個直角座標系,x軸上方有N個點。
現要求畫若干個圓心在x軸上,半徑爲R的圓,將N個點包含(內部或邊界)
輸入最小的圓的數量。
不存在則輸出-1
思路:
對於每個點分析,如縱座標大於R則不存在可行方案
否則在x軸上存在一區間上所有點皆符合條件(點間距小於或等於R)
子問題:線性區間選點
給定n個區間,要求選若干個點,保證每個區間內都有點被選,輸出點的最小數目
子問題思路:
將區間按照右邊界升序排序,相同右邊界也按升序排序。
每次選取當前區間最右點。然後跳過左邊界小於此點的區間繼續計數即可。
貪心思路證明:
對於當前區間選取中間某一點,同時影響了m個區間
將此點移動到本區間末,影響區間數目不會減小,甚至有可能影響更多的區間。
#include <stdio.h>
#include <algorithm>
#define LL long long
using namespace std;
struct aa
{
int l;
int r;
};
aa area[101000];
bool cmp(const aa &a, const aa &b)
{
if(a.r!=b.r)
return a.r < b.r;
return a.l < b.l;
}
int main()
{
int n, r;
int case_num = 1;
while(scanf("%d %d", &n, &r)==2 && (n||r))
{
int flag = 0;
for (int i = 0; i < n; i++)
{
int x, y;
scanf("%d %d", &x, &y);
if(y > r)
{
flag = 1;
continue;
}
int diff = 0;
for(; ;diff++)
if(((LL)diff*diff + (LL)y*y) > (LL)r*r)
break;
diff--;
area[i].l = x-diff;
area[i].r = x+diff;
}
if(flag)
{
printf("Case %d: -1\n", case_num++);
continue;
}
sort(area, area + n, cmp);
int res = 1;
int right = area[0].r;
for (int i = 1; i < n; ++i)
{
if(area[i].l>right)
{
res++;
right = area[i].r;
}
}
printf("Case %d: %d\n", case_num++, res);
}
}
WA