UVa 1432 Fire-Control System 解题报告(离散化 + 扫描)

56 篇文章 0 订阅

1432 - Fire-Control System

Time limit: 3.000 seconds

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:

\epsfbox{p4356.eps}

Here the firing region is the sector $ \overline{​{ABC}}$ 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.

Input 

There are multiple test cases in the input file.

Each test case starts with two non-negative integers, N and K (1$ \le$N$ \le$5000, K$ \le$N), 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.

Output 

For each test case, please print the required size (to two decimal places), in the format as indicated in the sample output.

Sample Input 

3 1 
0 1 
1 0 
-5 -6 

3 2 
0 2 
2 0 
-5 -6 

0 0

Sample Output 

Case #1: 0.00 
Case #2: 3.14


    用最小的扇形,覆盖n个点中的k个点。n的范围为5000。

    第一眼看上去不好搞。枚举扇形的左右边界,再让扇形覆盖k个点,复杂度略高( n^3 )。我们可以这样:将每个点到原点的距离离散化,枚举依次枚举该距离为扇形半径。扫描一遍所有点,如果点在这个半径形成的圆内,那么记录这个点的角度。排序角度,统计 i 点 到 i+k-1 点间的角度差,取最小值。以此最小值为扇形的张开角度,更新最小面积即可。注意会有k = 0的情况。代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <string>
using namespace std;

#define ff(i, n) for(int i=0;i<(n);i++)
#define fff(i, n, m) for(int i=(n);i<=(m);i++)
#define dff(i, n, m) for(int i=(n);i>=(m);i--)
#define mem(a) memset((a), 0, sizeof(a))
typedef long long LL;
typedef unsigned long long ULL;
void work();

int main()
{
#ifdef ACM
    freopen("in.txt", "r", stdin);
//    freopen("in.txt", "w", stdout);
#endif // ACM

    work();
}

/*****************************************/

struct Point
{
    double r, deg;

    bool operator<(const Point & cmp) const
    {
        return deg < cmp.deg;
    }
} p[5555];

const double pi = acos(-1.0);
int n, k;
double x, y;
double rr[5555];
double deg[11111];

double solve()
{
    sort(p, p+n);
    sort(rr, rr+n);
    int m = unique(rr, rr+n)-rr;

    double ans = 1e9;
    ff(i, m)
    {
        double maxr = rr[i];

        int tot = 0;
        ff(j, n) if(p[j].r <= maxr)
            deg[tot++] = p[j].deg;

        if(tot < k) continue;

        ff(j, k)
            deg[tot+j] = deg[j] + 2*pi;

        double mindeg = 2*pi;
        ff(j, tot)
            mindeg = min(mindeg, deg[j+k-1] - deg[j]);

        ans = min(ans, mindeg*maxr*maxr/2);
    }

    return ans;
}

void work()
{
    int cas = 1;
    while(~scanf("%d%d", &n, &k) && (n||k))
    {
        ff(i, n)
        {
            scanf("%lf%lf", &x, &y);
            rr[i] = p[i].r = sqrt(x*x + y*y);
            p[i].deg = acos(x/p[i].r);
            if(y < 0) p[i].deg = 2*pi - p[i].deg;
        }

        double ans = 0;
        if(k > 0)
            ans = solve();
        printf("Case #%d: %.2lf\n", cas++, ans);
    }
}


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值