Gym101915B、Ali and Wi-Fi (计算几何)

探讨在有限条件下,如何通过选择最佳位置,从多个Wi-Fi网络中获取最大总速度。涉及算法设计、点集处理和距离计算。

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

                                            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();
}

 

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值