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;
    }
    

    完结撒花❀

  • 相关阅读:
    将java库转换为.net库(转载)
    web sql设计器(连接)
    [SQLSERVER]SQL中的全文检索(转邹建)
    网络最经典命令行-网络安全工作者的必杀技
    无效的 CurrentPageIndex 值。它必须大于等于 0 且小于 PageCount。
    06毕业设计 VB导出Excel文档
    06毕业设计 VB导出word文档
    C# 交替显示项的DataGird,鼠标上移时转变颜色,退出后能恢复原来颜色
    js.offsetParent属性
    自动提醒IE6访客升级浏览器,
  • 原文地址:https://www.cnblogs.com/xxbbkk/p/15425202.html
Copyright © 2011-2022 走看看