A new mighty weapon has just been developed, which is so powerful that it can attack a sector of indefinite size, as long as the center of the circle containing the sector is the location of the weapon. We are interested in developing a fire-control system that calculates firing-solutions automatically.
The following example gives an example of a firing solution:
Here the firing region is the sector that covers six points: A, B, C, D, E, H.
You may further assume that the weapon is always located at point (0, 0), no targets will be on the point (0, 0) and the coordinates of the targets will be distinct.
A firing solution is called effective if and only if it covers a minimum of K points out of N given points (targets) on the two-dimensional Cartesian plane. Furthermore, since the cost of a particular fire solution is in direct proportion to the size of the area it covers, a firing could be quite costly; thus we are only interested in the optimal firing solution with the minimum cost.
There are multiple test cases in the input file.
Each test case starts with two non-negative integers, N and K (1N5000, KN) , followed by N lines each containing two integers, X , and Y , describing the distinct location of one target. It is guaranteed that the absolute value of any integer does not exceed 1000.
Two successive test cases are separated by a blank line. A case with N = 0 and K = 0 indicates the end of the input file, and should not be processed by your program.
For each test case, please print the required size (to two decimal places), in the format as indicated in the sample output.
3 1 0 1 1 0 -5 -6 3 2 0 2 2 0 -5 -6 0 0
Case #1: 0.00 Case #2: 3.14
题意:有一个武器在0,0。他的攻击范围是扇形。现在有n个点,要求能攻击到k个点,求最小的扇形面积。
思路:先枚举半径,在按点的极角排序,线性扫描满足半径的点维护ans即可。注意特判k==0的情况,被这个坑惨了还一直找不出来。复杂度为O(n^2)感觉不是很理想的复杂度,还是加点剪枝还是能rank1的
代码:
#include <stdio.h> #include <string.h> #include <math.h> #include <set> #include <algorithm> #define INF 0x3f3f3f3f #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) using namespace std; const int N = 5005; const double pi = acos(-1.0); void scanf_(int &num) { char in; bool neg=false; while(((in=getchar()) > '9' || in<'0') && in!='-') ; if(in=='-') { neg=true; while((in=getchar()) >'9' || in<'0'); } num=in-'0'; while(in=getchar(),in>='0'&&in<='9') num*=10,num+=in-'0'; if(neg) num=0-num; } int n, k; struct Point { int x, y; double r, p; int num; }p[N], save[N]; bool cmpr(Point a, Point b) { return a.r < b.r; } bool cmpp(Point a, Point b) { return a.p < b.p; } double cal(Point a, Point b) { return a.p - b.p; } double solve() { if(k == 0) return 0; int i, j; sort(p, p + n, cmpr); for (i = 1; i < n; i++) p[i].num += p[i - 1].num; double ans = INF; sort(p, p + n, cmpp); set<double> vis; for (i = 0; i < n; i++) { if (p[i].num < k) continue;//剪枝1 int sn = 0; double R = p[i].r, Minp = INF; if (vis.find(R) != vis.end()) continue;//剪枝2 vis.insert(R); for (j = 0; j < n; j++) { if (p[j].r < R || fabs(p[j].r - R) < 1e-9) { save[sn++] = p[j]; if (sn >= k) Minp = min(Minp, cal(save[sn - 1], save[sn - k])); } } if (sn < k) continue; for (j = 0; j < k - 1; j++) Minp = min(Minp, cal(save[j], save[(j - k + 1 + sn)]) + 2 * pi); ans = min(ans, R * R * Minp / 2); } return ans; } int main() { int cas = 0; while (~scanf("%d%d", &n, &k) && n + k) { for (int i = 0; i < n; i++) { scanf_(p[i].x); scanf_(p[i].y); p[i].r = sqrt(p[i].x * p[i].x + p[i].y * p[i].y); p[i].p = atan2(p[i].y, p[i].x); p[i].num = 1; } printf("Case #%d: %.2lf\n", ++cas, solve()); } return 0; }