zoukankan      html  css  js  c++  java
  • 题解[ [HNOI2011]数矩形 ]

    题目

    Luogu

    darkbzoj

    Sol

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

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

    把全部的直线求出来。

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

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

    那就好办了:把所有的(dfrac{ncdot(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
    ",ans);
    	return 0;
    }
    

    完结撒花❀

  • 相关阅读:
    XML与JSON的区别?各自有哪些优缺点?
    js数组操作(增、删、改、查)
    Ajax缓存原理
    Ajax的跨域问题分析
    简单理解javascript的闭包
    CSS的导入方式:link与import方式的区别
    谈谈iframe的优缺点
    winform全局异常捕获
    Dispatcher.BeginInvoke()方法使用不当导致UI界面卡死的原因分析
    解决asp.net中“从客户端中检测到有潜在危险的Request.Form值”的错误
  • 原文地址:https://www.cnblogs.com/xxbbkk/p/15425202.html
Copyright © 2011-2022 走看看