您的位置:首页 > 其它

UVALIVE 3954 Phone Cell <离散化 + 圆相交关系〉

2016-07-16 19:31 295 查看
题目:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1955

题意:如今时代,手机打电话,需要BTS信息收发电台发射信号,呈圆形发布。给你手机的坐标,发射范围为r,求出一台发射器覆盖手机数最多多少?

知识点:数学,离散化,坐标转换,极坐标

问题分析:这道题,由于圆心不知道,一开始,可能会想到模拟退火算法,然而这道题没有给x,y的坐标范围,不能使用。最终采用离散化

解题思路:每一个点分别作为极坐标原点,然后一一取其他求圆心极坐标角度范围,求出重合区间最多多少个,个数既是ans,取最大,最终结果就是max(ans+1)

时间复杂度:n^2logn

暑假这么热,每天热得不想起床,今早又逃课了。。。老衲罪过罪过

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <iostream>
#include <algorithm>
#define eps 1e-9
#define PI acos(-1.0)

using namespace std ;

struct Point
{
double x,y;
} pt[2005];

struct Node
{
double angle;
int flag;
} node[10005];

bool cmp(const Node& a,const Node& b)
{
if(a.angle - b.angle >-eps && a.angle - b.angle < eps) return a.flag > b.flag;
return a.angle < b.angle;
}

double dist(Point& a,Point& b)
{
return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}
int main()
{
int n,m;
while(scanf("%d %d",&n,&m) == 2&&n)
{
int i,j;
for(i=0; i<n; i++)
{
scanf("%lf %lf",&pt[i].x,&pt[i].y);
}
double d;
double temp,an;
int ans = 0,sum,k;
for(i=0; i<n; i++)
{
k = 0;
for(j=0; j<n; j++)
{
if(i == j) continue;
d = dist(pt[i],pt[j]);
if( d - 2*m > eps ) continue;
an  =  atan2(pt[j].y - pt[i].y,pt[j].x - pt[i].x);
if(an < 0)  an += 2*PI;
temp = acos(d/2.0/m);
node[k].angle = an - temp + 2*PI;
node[k].flag = 1;
k++;
node[k].angle = an + temp + 2*PI;
node[k].flag = -1;
k++;
}
sum = 0;
sort(node,node+k,cmp);
for(j=0; j<k; j++)
{
ans = max(ans,sum += node[j].flag);
}

}
printf("It is possible to cover %d points.\n",ans + 1);
}
return 0;
}


补充一下:



如上图,设A、B为点集中的两个点, 分别以A、B为圆心作单位圆,则相交范围内的任意位置作新的单位圆,都可以同时包含A与B,如圆C,如果把C放在一个其中一个圆A的圆周上,则圆C的圆周会穿过点A。

假设已得到题目的一个解圆O,则把得到的圆O通过移动,总可以让圆内的某个点X靠在圆周上,换言之,O也在X所作单位圆的圆周上。

由此,可枚举在最终结果的圆周上的点X,目标圆心O在X的圆周上。

每枚举一个X作为图中的点A,枚举其他所有点作为点B,可得到C对应点A、B的在A圆周上的一个范围,覆盖次数最多的那个范围就是当X作为点O圆周上的点所能得到的最优解O的范围,这个次数加1(点X)就是对应X的最优解。

通过枚举所有X,更新出最优解。

覆盖范围可以用圆周角表示,则为区间覆盖问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: