Ali and Wi-Fi
Ali lives in a very crowded city and a very large apartment. His apartment looks like an almost infinite 2D plane. In this city almost all his neighbors have WiFi networks, except for him. Precisely, from his apartment his laptop can receive NWiFi networks.
One day Ali wrote a program that can hack his neighbors' WiFi networks. Furthermore, he learned how to stand in a point, hack almost all the WiFi networks that reaches that point, and join them in one ultra-speed network.
Each WiFi network is described as a circle with its center on the point (x, y), a radius equal to R and a network speed equal to S.
However, Ali's program can join at most M networks. When Ali's program joins many networks, the resulting network will have the total sum for speeds of all networks.
Ali wants to choose a point at his apartment that will get him the maximum total speed of WiFi networks. Can you help him calculate the maximum total WiFi network speed he can get if he chooses his location optimally?
Input
The first line contains an integer T, the number of test cases.
The first line of each test contains (1 ≤ N ≤ 100) the number of WiFi networks and (1 ≤ M ≤ 100) the maximum number of networks Ali can join.
The following N line contains the description of N WiFi networks. The center coordinates (0 ≤ x, y ≤ 103) , the radius (1 ≤ R ≤ 103) and the network speed (0 ≤ S ≤ 106) .
Output
For each test case print a single line, containing a single integer, denoting the maximum total WiFi network speed Ali can get, if he chooses his location optimally.
Example
Input
1 3 2 0 0 2 5 4 0 1 10 2 2 4 2
Output
12
一、原题地址
二、大致题意
给定n个圆,每个圆有自己的权值。当你属于一个圆的范围内时,你就可以得到这个圆的权值。现在给定一个m,表示你最多能只能选择m个圆并得到权值,现在询问你所处在某一个地方能得到的最大的权值和。输出这个和。
三、思路
枚举出每两个圆相交的点,将他们加入一个集合stc[ ]待处理,并且把所有的圆心都加入到这个集合中(为了防止圆与圆没有重叠)。然后再枚举这些点到达所有圆的距离,看时候能得到权值,并且更新ans。
需要注意的是,在判断距离的时候需要使用精度来限制,仅比较大小会WA。
四、代码
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<functional>
#include<cmath>
using namespace std;
const int inf = 0x3f3f3f3f;
const long long int INF = 1e18;
typedef long long LL;
int T, n, m;
const double eps = 1e-8;
//const double inf = 1e20;
const double pi = acos(-1.0);
//const int maxp = 1010;
//Compares a double to zero
int sgn(double x)
{
if (fabs(x) < eps)return 0;
if (x < 0)return -1;
else return 1;
}
//square of a double
struct Point
{
double x, y;
Point() {}
Point(double _x, double _y) {x = _x;y = _y;}
Point operator - (const Point &b)const {
return Point(x - b.x, y - b.y);
}
//点积
Point trunc(double r) {
double l = len();
if (!sgn(l))return *this;
r /= l;
return Point(x*r, y*r);
}
//返回长度
Point rotleft() {
return Point(-y, x);
}
//顺时针旋转 90 度
Point rotright() {
return Point(y, -x);
}
double len() {
return hypot(x, y);//库函数
}
//返回两点的距离
double distance(Point p) {
return hypot(x - p.x, y - p.y);
}
Point operator +(const Point &b)const {
return Point(x + b.x, y + b.y);
}
};
struct circle {
Point p;//圆心
double r, val;
circle() {}
circle(Point _p, double _r) {p = _p;r = _r;}
circle(double x, double y, double _r) {
p = Point(x, y);
r = _r;
}
//点和圆的关系
//0 圆外
//1 圆上
//2 圆内
int relation(Point b) {
double dst = b.distance(p);
if (sgn(dst - r) < 0)return 2;
else if (sgn(dst - r) == 0)return 1;
return 0;
}
//两圆的关系
//5 相离
//4 外切
//3 相交
//2 内切
//1 内含
//需要 Point 的 distance
int relationcircle(circle v) {
double d = p.distance(v.p);
if (sgn(d - r - v.r) > 0)return 5;
if (sgn(d - r - v.r) == 0)return 4;
double l = fabs(r - v.r);
if (sgn(d - r - v.r)<0 && sgn(d - l)>0)return 3;
if (sgn(d - l) == 0)return 2;
if (sgn(d - l)<0)return 1;
}
//求两个圆的交点,返回 0 表示没有交点,返回 1 是一个交点,2 是两个交点
//需要 relationcircle
int pointcrosscircle(circle v, Point &p1, Point &p2) {
int rel = relationcircle(v);
if (rel == 1 || rel == 5)return 0;
double d = p.distance(v.p);
double l = (d*d + r*r - v.r*v.r) / (2 * d);
double h = sqrt(r*r - l*l);
Point tmp = p + (v.p - p).trunc(l);
p1 = tmp + ((v.p - p).rotleft().trunc(h));
p2 = tmp + ((v.p - p).rotright().trunc(h));
if (rel == 2 || rel == 4)
return 1;
return 2;
}
}cir[500];
Point stc[200005];
int main()
{
scanf("%d", &T);
while (T--)
{
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++)
{
scanf("%lf %lf %lf %lf",
&cir[i].p.x, &cir[i].p.y,
&cir[i].r, &cir[i].val);
}
int tot = 0;
for (int i = 1; i <= n; i++)
{
stc[tot++] = cir[i].p;
for (int j = i + 1; j <= n; j++)
{
if (i == j)continue;
Point t1, t2;
int bac=cir[i].pointcrosscircle(cir[j], t1, t2);
if (bac == 1)
{
stc[tot++] = t1;
}
else if (bac == 2)
{
stc[tot++] = t1;
stc[tot++] = t2;
}
}
}
double ans = 0;
for (int i = 0; i < tot; i++)
{
priority_queue<double>q;
for (int j = 1; j <= n; j++)
{
if (cir[j].p.distance(stc[i])- cir[j].r <= eps)
q.push(cir[j].val);
}
double sum = 0;
for (int j = 0; j < m; j++)
{
if (q.empty())break;
sum += q.top();
q.pop();
}
ans = max(ans, sum);
}
printf("%.0f\n", ans);
}
getchar();
getchar();
}
探讨在有限条件下,如何通过选择最佳位置,从多个Wi-Fi网络中获取最大总速度。涉及算法设计、点集处理和距离计算。
363

被折叠的 条评论
为什么被折叠?



