P3744 李彬的几何 题解

· · 题解

1. 题意解释

给出一个凸多边形各点的坐标,求移动若干个点使此凸多边形变成非凸多边形的最小移动距离。

2. 思路

这是一道很水的数学题。

我们知道,在凸多边形中,每个顶点与另外两个顶点相连(显然,不知道的重学初等几何)。

而根据凸多边形的定义,这三点显然是不共线的。

所以假如我们让这三点共线,这个多边形即不再是凸多边形。

为方便,我们记两边的两点分别为 AB,记与 AB 都相连的点为 C

我们的目标也就是把 C 移动到线段 AB 上。

容易知道,我们过 CAB 的垂线 CHAB 相交与点 H,则 CH 是移动的最小距离。

海伦公式、秦九韶公式、割补法、行列式法随你选,爱用哪个用哪个。 求出 $CH$ 后,仍然不是最终的答案。 由于我们可以不止移动一个点,我们可以让 $AB$ 整体向上移动 $\dfrac{CH}{2}$ 的距离,$C$ 点也移动 $\dfrac{CH}{2}$ 的距离,则 $C$ 点仍落在 $AB$ 上。 因此最终答案为 $\dfrac{CH}{2}$ 的最小值。 由于题目保证点按照顺时针顺序给出,因此处理并不难,在此不多赘述。 ### 3. 代码实现 记得多开几个 double。 ```cpp #include<bits/stdc++.h> using namespace std; int n; struct data{ double x,y; }a[1010]; double ans=1e9; double calc(int p,int q,int j){ return abs(a[p].x*a[q].y+a[q].x*a[j].y+a[j].x*a[p].y-a[p].x*a[j].y-a[q].x*a[p].y-a[j].x*a[q].y)/2; } double dist(int p,int q){ return sqrt((a[p].x-a[q].x)*(a[p].x-a[q].x)+(a[p].y-a[q].y)*(a[p].y-a[q].y)); } int main(){ cin>>n; for(int i=1;i<=n;i++){ cin>>a[i].x>>a[i].y; } a[n+1].x=a[1].x,a[n+1].y=a[1].y; a[0].x=a[n].x,a[0].y=a[n].y; for(int i=1;i<=n;i++){ double S=calc(i-1,i,i+1); double l=dist(i-1,i+1); double d=S/l; ans=min(ans,d); } cout<<ans; return 0; } ```