Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 68597 | Accepted: 15373 |
Description
We use
Cartesian coordinate system, defining the coasting is the x-axis. The sea side
is above x-axis, and the land side below. Given the position of each island in
the sea, and given the distance of the coverage of the radar installation, your
task is to write a program to find the minimal number of radar installations to
cover all the islands. Note that the position of an island is represented by its
x-y coordinates.
Figure A Sample Input of Radar
Installations
Input
line of each case contains two integers n (1<=n<=1000) and d, where n is
the number of islands in the sea and d is the distance of coverage of the radar
installation. This is followed by n lines each containing two integers
representing the coordinate of the position of each island. Then a blank line
follows to separate the cases.
The input is terminated by a line
containing pair of zeros
Output
test case number followed by the minimal number of radar installations needed.
"-1" installation means no solution for that case.
Sample Input
3 2
1 2
-3 1
2 1 1 2
0 2 0 0
Sample Output
Case 1: 2
Case 2: 1 http://blog.csdn.net/zxiaopp/article/details/48845201
数轴上有n个闭区间[ai,bi]。取尽量少的点,使得每个区间内都至少有一个点(不同区间内含的点可以是同一个)。
贪心策略:
按照b1<=b2<=b3…(b相同时按a从大到小)的方式排序排序,从前向后遍历,当遇到没有加入集合的区间时,选取这个区间的右端点b。
证明:
为了方便起见,如果区间i内已经有一个点被取到,我们称区间i被满足。
1、首先考虑区间包含的情况,当小区间被满足时大区间一定被满足。所以我们应当优先选取小区间中的点,从而使大区间不用考虑。
按照上面的方式排序后,如果出现区间包含的情况,小区间一定在大区间前面。所以此情况下我们会优先选择小区间。
则此情况下,贪心策略是正确的。
不一定要按照正规解法,第一次我b相同,并不是按照a从大到小排序,而是a从小到大排序,其实怎么排序都可以,只要看最后的截止时间就ok了,如果下一个的开始时间在截止时间之前,那么可以用一个点覆盖,如果在后面,只需要两个点,然后更新到后面那个的截止时间,只要开始时间在截止前面一定不需要新的一个点来覆盖了。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;
const int MAX = + ;
const double eps = 10e-;
struct Rader
{
double a,b;
};
Rader rader[MAX];
int cmp(Rader x, Rader y)
{
if(fabs(x.b - y.b) <= eps)
return x.a < y.a;
return (x.b - y.b) < -eps;
}
int main()
{
int n,d,flag,tase = ;
double x, y, t;
while(scanf("%d%d", &n, &d) != EOF)
{
if(n == && d == )
break;
flag = ;
for(int i = ; i <= n; i++)
{
scanf("%lf%lf", &x, &y);
if(d < y)
{
flag = ;
continue;
}
t = sqrt(d * d - y * y);
rader[i].a = x - t;
rader[i].b = x + t;
}
printf("Case %d: ",++tase);
if(flag)
{
printf("-1\n");
}
else
{
sort(rader + , rader + + n, cmp);
int cnt = ;
double start = rader[].b;
for(int i = ; i <= n; i++)
{
if(start - rader[i].a < -eps)
{
start = rader[i].b;
cnt++;
}
}
printf("%d\n", cnt);
} } return ;
}
b从小到大排序
之后又想了想可不可以针对a来排序,结果也是可以的,就对a从小到大咯,如果下一个的截止时间在这个截止时间之前不用新的点覆盖,但要更新到后一个的截止时间,对,因为要以小区间为基准;如果下一个的开始时间在截止时间之后那么一定得需要一个新的点来覆盖了,同时更新到后一个的截止时间
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;
const int MAX = + ;
const double eps = 10e-;
struct Rader
{
double a,b;
};
Rader rader[MAX];
int cmp(Rader x, Rader y)
{
// if(fabs(x.b - y.b) <= eps)
// return x.a < y.a;
return (x.a - y.a) < -eps;
}
int main()
{
int n,d,flag,tase = ;
double x, y, t;
while(scanf("%d%d", &n, &d) != EOF)
{
if(n == && d == )
break;
flag = ;
for(int i = ; i <= n; i++)
{
scanf("%lf%lf", &x, &y);
if(d < y)
{
flag = ;
continue;
}
t = sqrt(d * d - y * y);
rader[i].a = x - t;
rader[i].b = x + t;
}
printf("Case %d: ",++tase);
if(flag)
{
printf("-1\n");
}
else
{
sort(rader + , rader + + n, cmp);
int cnt = ;
double start = rader[].b;
for(int i = ; i <= n; i++)
{
if(start - rader[i].b > eps)
{
start = rader[i].b;
}
else if(start - rader[i].a < -eps)
{
start = rader[i].b;
cnt++;
}
}
printf("%d\n", cnt);
} } return ;
}
a从小到大