Problem
给你n个点的坐标和权值,然后一个点最多可以经过1次,最后要回到原点,求这条路径中包含的点的权值和除以路径长度的最大值。
Solution
我们可以很明显的得知,这条路径是个凸包(否则不但包含的点少了,路径也长了)
我们可以二分答案,然后用一个dp来验证答案:
所以我们用f[i]表示枚举到第i个点后的值,最后判断是否大于等于0

如果我们可以快速算出一个颜色的三角形内的点权之和,则这个DP是可以O(n^2)实现的。
我们可以用O(n^3)大暴力来预处理。(期望得分:60)
如果我们可以尝试用O(n^2logn)来预处理,那么就可以A了此题

如果k在这个三角形的内部,那么关于p的极角排序,k在j的前面,关于i的极角排序,k在j的后面,
那么这就转换成了一个二维数点问题,时间复杂度为O(n*(nlogn+nlogn))。(期望得分:100)
Notice
计算几何代码十分复杂
Code
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define sqz main
#define ll long long
#define reg register int
#define lowbit(x) (x & -x)
#define rep(i, a, b) for (reg i = a; i <= b; i++)
#define per(i, a, b) for (reg i = a; i >= b; i--)
#define travel(i, u) for (reg i = head[u]; i; i = edge[i].next)
const int INF = 1e9, N = 2000;
const double eps = 1e-6, phi = acos(-1.0);
ll mod(ll a, ll b) {if (a >= b || a < 0) a %= b; if (a < 0) a += b; return a;}
ll read(){ ll x = 0; int zf = 1; char ch; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
if (ch == '-') zf = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;}
void write(ll y) { if (y < 0) putchar('-'), y = -y; if (y > 9) write(y / 10); putchar(y % 10 + '0');}
int n, Sum[N + 5][N + 5];
double f[N + 5];
struct node
{
int X[N + 5];
void build(int l, int r)
{
rep(i, l, r) X[i] = 0;
}
void modify(int x, int y)
{
while(x < n)
{
X[x]+= y;
x += lowbit(x);
}
}
int query(int x)
{
int ans = 0;
while (x)
{
ans += X[x];
x -= lowbit(x);
}
return ans;
}
}BIT;
struct point
{
double x, y;
point(double x = 0, double y = 0) : x(x), y(y) {}
friend double operator *(const point &X, const point &Y)
{
return X.x * Y.y - X.y * Y.x;
}
friend double operator %(const point &X, const point &Y)
{
return X.x * Y.x + X.y * Y.y;
}
friend point operator +(const point &X, const point &Y)
{
return point(X.x + Y.x, X.y + Y.y);
}
friend point operator -(const point &X, const point &Y)
{
return point(X.x - Y.x, X.y - Y.y);
}
double dis(const point &Y)
{
return sqrt((x - Y.x) * (x - Y.x) + (y - Y.y) * (y - Y.y));
}
}Standard;
pair<point, int> T[N + 5], D[N + 5];
int cmp(pair<point, int> X, pair<point, int> Y)
{
if (abs((X.first - Standard) * (Y.first - Standard)) < eps) return X.first.x < Y.first.x;
else return (X.first - Standard) * (Y.first - Standard) > 0;
}
int calc(double mid)
{
f[0] = 0; f[n] = -INF;
rep(i, 1, n - 1) f[i] = T[i].second - mid * T[i].first.dis(T[0].first);
rep(i, 1, n - 1)
rep(j, i + 1, n)
f[j] = max(f[j], f[i] + Sum[i][j] - mid * T[j].first.dis(T[i].first));
return f[n] >= 0;
}
double find(double l, double r)
{
if (abs(l - r) < eps) return l;
double mid = (l + r) / 2;
if (calc(mid)) return find(mid, r);
else return find(l, mid);
}
int sqz()
{
n = read();
Standard = point(0, 0);
rep(i, 1, n)
{
int x = read(), y = read();
T[i] = make_pair(point(x, y), read());
}
sort(T + 1, T + n + 1, cmp);
T[0] = make_pair(point(0, 0), 0), T[++n] = T[0];
rep(i, 1, n - 1)
{
Sum[i][n] = 0;
rep(j, i + 1, n - 1) D[j] = make_pair(T[j].first, j);
Standard = T[i].first;
sort(D + i + 1, D + n, cmp);
BIT.build(0, n);
per(j, n - 1, i + 1)
{
BIT.modify(D[j].second, T[D[j].second].second);
Sum[i][D[j].second] = BIT.query(D[j].second);
}
}
printf("%.3lf\n", find((double)0, (double)2e8));
return 0;
}
浙公网安备 33010602011771号