【POJ3004】Subway planning——扫描线

22 篇文章 0 订阅
6 篇文章 0 订阅

Subway planning

Time Limit: 2000MS Memory Limit: 65536K

Description

The government in a foreign country is looking into the possibility of establishing a subway system in its capital. Because of practical reasons, they would like each subway line to start at the central station and then go in a straight line in some angle as far as necessary. You have been hired to investigate whether such an approach is feasible. Given the coordinates of important places in the city as well as the maximum distance these places can be from a subway station (possibly the central station, which is already built), your job is to calculate the minimum number of subway lines needed. You may assume that any number of subway stations can be built along a subway line.
3004_1.jpg

Figure 1: The figure above corresponds to the first data set in the example input.

Input

The first line in the input file contains an integer N, the number of data sets to follow. Each set starts with two integers, n and d (1 ≤ n ≤ 500, 0 ≤ d < 150). n is the number of important places in the city that must have a subway station nearby, and d is the maximum distance allowed between an important place and a subway station. Then comes n lines, each line containing two integers x and y (-100 ≤ x, y ≤ 100), the coordinates of an important place in the capital. The central station will always have coordinates 0, 0. All pairs of coordinates within a data set will be distinct (and none will be 0, 0).
Output

For each data set, output a single integer on a line by itself: the minimum number of subway lines needed to make sure all important places in the city is at a distance of at most d from a subway station.
Sample Input

2
7 1
-1 -4
-3 1
-3 -1
2 3
2 4
2 -2
6 -2
4 0
0 4
-12 18
0 27
-34 51
Sample Output

4
2

题意:平面直角坐标系中有一些点代表着一些城市。国家要在(0,0)点设置中心车站并向建设地铁线路,但要求线路是直线。某个城市可以使用地铁线路的前提是它与线路的直线距离不超过d。问最少建设多少条线路才能让所有的城市都能使用地铁。

分析:首先对于距离原点(0,0)的距离小于d的城市,我们没有必要取考虑,对于剩下的城市,我们可以算出每一个城市想要被地铁穿过的角度的范围 [Li,Ri] ,所以问题就转化为区间覆盖的问题,但是我们不知道以哪一个城市为起点会得到最优的解,所以要枚举一下起点。

#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <iostream>
#include <algorithm>

using namespace std;

const double eps = 1e-6;

const double Pi = acos(-1.0);

const int Max = 1100;

typedef struct node
{
    double x,y;

    double l,r;

    node(){}

    node(double _x,double _y):x(_x),y(_y){}

    node operator + (const node &a)const
    {
        return node(x+a.x,y+a.y); 
    }

    node operator - (const node &a)const
    {
        return node(x-a.x,y-a.y);
    }

    double operator * (const node &a)const
    {
        return a.x*x+a.y*y;
    }

    double operator ^ (const node &a)const
    {
        return x*a.y-y*a.x;
    }
}Circ;

int dbcmp(double a)//精度控制
{
    return fabs(a)<eps?0:(a>0?1:-1);
}

int JudgeQuadrant(node a)// 判断象限
{
    if(a.x >= 0 && a.y >= 0) return 1;

    if(a.x < 0 && a.y >= 0) return 2;

    if(a.x <= 0 && a.y < 0) return 3;

    if(a.x > 0 && a.y < 0) return 4;

    return 0;
}

double d;

double Judge(node a,int op)//计算区间
{
    int ant = JudgeQuadrant(a);

    double ans1 = fabs(asin(a.y/sqrt(a*a)));

    if(ant==2) ans1 = Pi-ans1;

    if(ant==3) ans1 = ans1+Pi;

    if(ant==4) ans1 = 2*Pi -ans1;

    if(op)
        return ans1 - asin(d/sqrt(a*a));
    else
        return ans1 + asin(d/sqrt(a*a));

}

bool cmp(node a,node b)
{
    return a.l<b.l;
}

Circ C[Max];

int n;

int main()
{
    int T;

    scanf("%d",&T);

    while(T--)
    {
        scanf("%d %lf",&n,&d);

        for(int i = 0;i<n;i++) 
        {
            scanf("%lf %lf",&C[i].x,&C[i].y);

            if(dbcmp(d*d-C[i]*C[i])>=0) 
            {
                i--,n--;

                continue;
            }

            C[i].l = Judge(C[i],1);

            C[i].r = Judge(C[i],0);
        }

        sort(C,C+n,cmp);

        for(int i =n ;i<2*n;i++)
        {
            C[i] = C[i-n];

            C[i].l +=2*Pi;

            C[i].r +=2*Pi;
        }

        int ans = n;

        for(int i = 0; i < n ; i++)
        {
            double r = C[i].r;

            int ant = 1;

            for(int j= i+1;j<i+n;j++)
            {
                if(dbcmp(r-C[j].r)>=0) r =C[j].r;

                else if(dbcmp(r-C[j].l)<0) 
                {
                    ant++;

                    r = C[j].r;
                }
            }

            ans = min(ans,ant);

        }
        printf("%d\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值