ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

题解[ [HNOI2011]数矩形 ]

2021-10-19 16:34:07  阅读:149  来源: 互联网

标签:直线 dfrac double HNOI2011 中垂线 题解 矩形 type define


题目

Luogu

darkbzoj

Sol

提供一个不用高级计算几何技巧的写法。

感觉和\(Atcoder\ ABC220G\)比较相似。

把全部的直线求出来。

考虑两条直线满足什么条件才会构成一个矩形的对边:

  • 两条直线的中垂线完全相同
  • 原本的两条直线不重合
  • 两条直线长度相同

那就好办了:把所有的\(\dfrac{n\cdot(n-1)}{2}\)条直线根据中垂线排序,同时设直线的中点为这条直线的标志点,两条中垂线相同且长度相同的直线若中点不同则可以构成矩形。

在所有中垂线相同的直线中,找到标志点横坐标的差最大的两条直线,算出面积,最后取最大值。

复杂度\(O(n^2log_2n)\)。

如何求点\((x_i,y_i)\)和点\((x_j,y_j)\)所成的直线的中垂线?

点\((x_i,y_i)\)​和点\((x_j,y_j)\)​所成的直线的斜率:\(k_1=\dfrac{y_j-y_i}{x_j-x_i}\)​

所以中垂线的斜率为\(k_2=\dfrac{-1}{k_1}\)

再根据中垂线经过中点\((\dfrac{x_i+x_j}{2},\dfrac{y_i+y_j}{2})\)即可求出截距\(b\)。

还有一个细节:若中垂线平行于\(y\)轴,就把\(k\)设为无穷大,\(b\)设为\(\dfrac{x_i+y_j}{2}\)。

Code

#include<bits/stdc++.h>
#define double long double
#define N (1510)
#define L (3000010)
#define ll long long
using namespace std;
struct Point{double x,y;}p[N];
struct Line{double k,b,x,y,l;int type;}ln[L];
int n,tot;
double ans;
inline bool cmp(Line a,Line b){
    //根据中垂线排序
	if(a.type!=b.type) return a.type<b.type;
	if(a.k!=b.k) return a.k<b.k;
	if(a.b!=b.b) return a.b<b.b;
	if(a.l!=b.l) return a.l<b.l;
	return a.x<b.x;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%Lf%Lf",&p[i].x,&p[i].y);
	for(int i=1;i<n;i++){
		for(int j=i+1;j<=n;j++){
            //求中垂线
			ln[++tot].type=0;
			double xi=p[i].x,xj=p[j].x,yi=p[i].y,yj=p[j].y;
			double X=xi-xj,Y=yi-yj;
			double k1=xj-xi,k2=yi-yj;
			double b1=yi*yi-yj*yj+xi*xi-xj*xj,b2=2*(yi-yj);
			ln[tot].x=(xi+xj)/2.0,ln[tot].y=(yi+yj)/2.0;
			ln[tot].l=sqrt(X*X+Y*Y);
			if(k2==0){
				ln[tot].k=1e18;
				ln[tot].type=1;
				ln[tot].b=(xi+xj)/2.0;
				continue;
			}
			double k=k1/k2,b=b1/b2;			
			ln[tot].k=k,ln[tot].b=b;
		}
	}
	sort(ln+1,ln+1+tot,cmp);
	for(int i=1;i<=tot;){
		int j=i+1;
        //找到最远的点j
		while(ln[j].k==ln[i].k&&ln[j].l==ln[i].l&&ln[j].b==ln[i].b&&j<=tot) ++j;
		--j;
		if(i!=j&&(ln[i].x!=ln[j].x||ln[i].y!=ln[j].y)){
			double X=ln[i].x-ln[j].x,Y=ln[i].y-ln[j].y;
			double len=sqrt(X*X+Y*Y);
			double res=ln[i].l*len;
			ans=max(ans,res);
		}
		i=j+1;
	}
	printf("%.0Lf\n",ans);
	return 0;
}

完结撒花❀

标签:直线,dfrac,double,HNOI2011,中垂线,题解,矩形,type,define
来源: https://www.cnblogs.com/xxbbkk/p/15425202.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有