题目概述

在平面直角坐标系的第$1$象限和第$4$象限有$n$个点,其中第$i$个点的坐标为$(x_i,y_i)$,有一个权值$p_i$

从原点$O(0,0)$出发,不重复的经过一些点,最终走到原点,围成一个多边形。我们定义开心程度为$f$。

设经过节点总共走的路径长度是$s$,最终路径围成的多边形中所有点的权值和为$w$,则$f = \frac{w}{s}$。

试最大化开心程度$f$。保留$3$位小数后输出$f_{min}$。

对于$100\%$的数据满足$n\leq 2\times 10^3 , 0 \leq x_i \leq 10^4 , |y_i| \leq 10^4 , 1\leq  p_i \leq 10^4$

Solution - 前置知识

本题考场由@ljc20020730胡出正解。涉及部分计算几何知识。

首先,我们需要知道向量叉积的计算方法和几何含义。

定义向量$\vec{a}$ 和 $\vec{b}$,则记向量叉积为$\vec{a} \times \vec{b}$

设向量坐标 $\vec{a} = (x_a,y_a) , \vec{b} = (x_b,y_b)$

其中,叉积的几何意义是一个垂直于$| \vec{a} $与$\vec{b}$构成平面的向量$c$,其模长$| \vec{a} \times \vec{b} | = |x_a y_b - x_by_a| $

其方向可以用右手螺旋定则确定(即右手四指从$\vec{a}$指向$\vec{b}$,大拇指所在方向就是叉积后向量方向)

于是,设点$A,B,C$,则可以使用向量叉积方便的判断点$A$在直线$BC$的左侧还是右侧。

若$|\vec{BA} \times \vec{BC}| > 0$则在直线$BC$的左侧;

若$|\vec{BA} \times \vec{BC}| = 0$在直线$BC$上;

若$|\vec{BA} \times \vec{BC}| < 0$则在直线$BC$的右侧;

这样,我们就可以判断$P$是否在由$A,B,C$构成的三角形内了。

$P,A$必须在直线$BC$的同侧,$P,B$必须在直线$AC$的同侧,$P,C$必须在直线$AB$的同侧。

  其次,我们还需要知道利用向量叉积进行极角排序的相关知识点。

  极角:设坐标轴$Ox$并规定逆时针为正方向,对任何点其到原点构成直线与坐标轴的夹角叫极角。

  显然,理论上,如果计算机非常准确,则极角排序可以使用反三角函数解决。

  对于两个点$(x_1,y_1), (x_2,y_2)$如果$(x_2,y_2)$在原点和$(x_1,y_1)$构成直线的右侧,则需要交换这两个点的顺序。

  这可以利用之前点在直线方向判定的叉积来实现。利用快速排序,可以做到$O(n \log_2 n)$

Solution 关于本题

 首先,答案具有单调性,我们可以二分快乐值$f$,现在问题是判定是否能找出一条方案,使得其快乐值大于二分的答案。

 记$\frac{w}{s} \geq f$由于$s > 0$则$w - fs \geq 0$,对于每次二分的定值$f$,最大化$w - fs$的值即可。

 我们首先会想到由于$w$是围成图形内包含点的权值和,我们首先按照$O(0,0)$进行极角排序。按照此时的顺序进行$DP$

 状态为$f[i]$表示最后一个经过点$i$的路径答案,显然$f[i] = max \{ f[j] + cost(i,j) \}$其中$cost(i,j)$表示极角排序后$i$点(不包含)到$j$点(包含)的元素的权值和。

 如果暴力计算$cost(i,j)$,时间复杂度是$O(n^3 log_2 n)$。我们必须离线处理$cost(i,j)$的值。

 首先,对极角排序后的$n$个点编成连续的编号$1- n$,设当前点是$i$,则将$i+1 - n$号点的权值,单点插入到树状数组对应编号位中,便于区间查询。

 这些插入的点对第$i$个点为基准进行极角排序(角相同则按照半径大优先),依次考虑。设当前考虑到点$j$。

 为了计算$cost(i,j)$,我们需要知道,树状数组区间中i的编号到j的编号之间的答案和。

 可以证明,经过这两次极角排序后,i的编号到j的编号之间的点$k$,在以$i$和$j$和$O(0,0)$构成的三角形中了。

 然后,由于该点在后续的点将不再会被用到,故在树状数组中单点删除即可。

 于是,我们可以在$O(n^2 log_2 n)$的复杂度为维护$cost(i,j)$了。

 对于$DP$的转移也就变成$O(1)$的了。

 本题最终时间复杂度是$O(n^2 \log_2 n)$

# pragma GCC optimize()
# include <bits/stdc++.h>
using namespace std;
const int N=2e3+;
int n,g[N][N],c[N];
inline int read()
{
int X=,w=; char c=;
while(c<''||c>'') {w|=c=='-';c=getchar();}
while(c>=''&&c<='') X=(X<<)+(X<<)+(c^),c=getchar();
return w?-X:X;
}
# define lowbit(x) (x&(-x))
void update(int x,int d) { for (;x<=n;x+=lowbit(x)) c[x]+=d;}
int query(int x) { int ret=; for (;x;x-=lowbit(x)) ret+=c[x]; return ret;}
int query(int l,int r) {return query(r)-query(l-);}
struct rec{ int x,y,p; }a[N],b[N],tmp[N];
int cross(rec a,rec b) { return a.y*b.x-a.x*b.y;}
int direct (rec a,rec b,rec c) {
rec ba={a.x-b.x,a.y-b.y,};
rec bc={c.x-b.x,c.y-b.y,};
int ret=cross(ba,bc);
if (ret==) return ;
else if (ret<) return -;
else if (ret>) return ;
}
bool triangle(rec p,rec a,rec b,rec c) {
if (direct(p,b,c)*direct(a,b,c)<) return false;
if (direct(p,a,c)*direct(b,a,c)<) return false;
if (direct(p,a,b)*direct(c,a,b)<) return false;
return true;
}
bool cmp1(rec a,rec b) {
return (direct(b,{,,},a)>);
}
bool operator == (rec a,rec b) {
return a.x==b.x && a.y==b.y && a.p==b.p;
}
int cx,cy;
bool cmp2(rec a,rec b) {
int ret=direct(b,(rec){cx,cy,},a);
if (ret) return ret>;
return (a.x-cx)*(a.x-cx)+(a.y-cy)*(a.y-cy) > (b.x-cx)*(b.x-cx)+(b.y-cy)*(b.y-cy);
}
double dist(int i,int j) {
return sqrt((a[j].y-a[i].y)*(a[j].y-a[i].y) + (a[j].x-a[i].x)*(a[j].x-a[i].x));
}
double f[N];
bool check(double mid) {
for (int i=;i<=n;i++)
f[i]=a[i].p-mid*dist(,i);
for (int i=;i<n;i++)
for (int j=i+;j<=n;j++)
f[j]=max(f[j],f[i]+g[i][j]-mid*dist(i,j));
double ans=-1e9;
for (int i=;i<=n;i++) ans=max(ans,f[i]-dist(i,)*mid);
return ans>;
}
int main() {
n=read(); a[].x=a[].y=;
for (int i=;i<=n;i++)
a[i].x=read(),a[i].y=read(),a[i].p=read();
sort(a+,a++n,cmp1);
memcpy(b,a,sizeof(a));
for (int i=;i<=n;i++) b[i].p=i;
for (int i=;i<=n;i++) {
memset(c,,sizeof(c));
int cnt=;
for (int j=i+;j<=n;j++) {
tmp[++cnt]=b[j];
update(j,a[j].p);
}
cx=a[i].x; cy=a[i].y;
sort(tmp+,tmp++cnt,cmp2);
for (int j=;j<=cnt;j++) {
g[i][tmp[j].p]=query(i,tmp[j].p);
update(tmp[j].p,-a[tmp[j].p].p);
}
}
double l=,r=2e7,ans;
while (r-l>1e-) {
double mid=(l+r)/2.0;
if (check(mid)) ans=mid,l=mid;
else r=mid;
}
printf("%.3lf\n",ans);
return ;
}

cruise.cpp

『HGOI 20190917』Cruise 题解 (计算几何+DP)的更多相关文章

  1. 『HGOI 20190917』Lefkaritika 题解 (DP)

    题目概述 一个$n \times m$的整点集.其中$q$个点被m被设置为不能访问. 问这个点集中含有多少个不同的正方形,满足不包含任何一个不能访问的点. 对于$50\%$的数据满足$1 \leq n ...

  2. LuoguP7337 『MdOI R4』Fun 题解

    Content 有 \(n\) 个人去打比赛.给出第 \(i\) 个人的交通方式 \(t_i\) 和颓废值 \(q_i\)(均以 \(0/1\) 表示).如果 \(t_i=1,q_i=1\) 的人数 ...

  3. 关于『进击的Markdown』:第二弹

    关于『进击的Markdown』:第二弹 建议缩放90%食用 众里寻他千百度,蓦然回首,Markdown却在灯火灿烂处 MarkdownYYDS! 各位早上好!  我果然鸽稿了  Markdown 语法 ...

  4. 似魔鬼的 『 document.write 』

    在平时的工作中,楼主很少用 document.write 方法,一直觉得 document.write 是个危险的方法.楼主不用,并不代表别人不用,最近给维护的项目添了一点代码,更加深了我对 &quo ...

  5. 拾遗:『Linux Capability』

    『Linux Capability』 For the purpose of performing permission checks, traditional UNIX implementations ...

  6. 『创意欣赏』20款精致的 iOS7 APP 图标设计

    这篇文章给大家分享20款精致的 iOS7 移动应用程序图标,遵循图形设计的现代潮流,所有图标都非常了不起,给人惊喜.通过学习这些移动应用程序图标,设计人员可以提高他们的创作,使移动用户界面看起来更有趣 ...

  7. 『设计前沿』14款精致的国外 iOS7 图标设计示例

    每天都有大量的应用程序发布到 iOS App Store 上,在数量巨大的应用中想要引起用户的主要,首要的就是独特的图标设计.这篇文章收集了14款精致的国外 iOS7 图标设计示例,希望能带给你设计灵 ...

  8. Github 恶搞教程(一起『玩坏』自己的 Github 吧)

    最近在伯乐在线读到一篇趣文,<如何在 Github『正确』做贡献>,里面各种能人恶搞 Github 的『Public contributions』,下面截取几个小伙伴的战绩: 顺藤摸瓜,发 ...

  9. 『创意欣赏』30幅逼真的 3D 虚拟现实环境呈现

    又到周末了,给大家分享30幅漂亮的 3D 虚拟现实环境呈现,放松一下.这些创造性的场景都是通过 3D 图形设计软件,结合三维现实环境渲染制作出来的.一起欣赏:) 您可能感兴趣的相关文章 20幅温馨浪漫 ...

随机推荐

  1. day03-04

    光驱 历史的东西 远程管理卡 ​ 它的作用是通过网络远程(异地)开关服务器,并可以查看服务器开关的过程等信息,早期(2010年以前),服务器托管在IDC机房,出问题,还得跑机房或者请机房的人管理,有了 ...

  2. 【二分】Shell Pyramid

    [来源]:2008年哈尔滨区域赛 [题目链接]: http://acm.hdu.edu.cn/showproblem.php?pid=2446 [题意] 题目是真的长呀,其实就问一个问题. 按照图里面 ...

  3. 安装kubenetes-遇到的问题总结

    # 5.修改docker的cgroup驱动(不需要操作)# kubelet# 看到最后一行:error: failed to run Kubelet: failed to create kubelet ...

  4. SQL SERVER 语法

    1.获取所有用户名: Select name FROM Sysusers where status='2' and islogin='1' islogin='1' :表示帐户 islogin='0' ...

  5. Parallel的使用

    Action<int, int> ReportProcess //返回数据,刷新进度 Exception exception = null; object objLock = new ob ...

  6. 【html】 iframe 和 frameset 的区别

    一.两者的相同点和不同点 相同点: iframe 和frameset都是html布局的框架布局 不同点: iframe是一个内联框架,是在页面里生成内部框架 frameset定义一个框架集,包含多个子 ...

  7. react绑定事件的几种写法

    方法一:最麻烦的写法,不推荐 import React from 'react'; class App extends React.Component { handleClick() { alert( ...

  8. SSE笔记

    1.8位加: *(__m128i*)(dest + i * 16) = _mm_add_epi8(*(__m128i*)(srcA + i * 16), *(__m128i*)(srcB + i * ...

  9. haproxy实现ssl套接字加密

    概述 如果你的应用使用SSL证书,则需要决定如何在负载均衡器上使用它们. 单服务器的简单配置通常是考虑客户端SSL连接如何被接收请求的服务器解码.由于负载均衡器处在客户端和更多服务器之间,SSL连接解 ...

  10. Samba Server 的使用者帳號及密碼備份

    Samba Server 自從 3.x 後改成使用 tdbsam 的方式來管理使用者的帳號及密碼,原本的帳號密碼都是存放在 /etc/samba 目錄之下,最近要做備份時,一時之間竟然找不到 Samb ...