• nyoj 952 最大四边形 计算几何 转载


    事实再一次证明:本小菜在计算几何上就是个渣啊,唉,,,

    题意:平面上n个点(n<=300),问任意四个点组成的四边形(保证四条边不相交)的最大面积是多少。

    分析:

    原文地址

    1、第一思路是枚举四个点,以O(n4)的算法妥妥超时。

    2、以下思路源自官方题解

      以O(n2)枚举每一条边,以这条边作为四边形的对角线(注意:这里所说的 对角线是指把四边形分成两部分的线,不考虑凹四边形可能出现的两个点在对角线同一侧的情况),以O(n)枚举每一个点,判断是在对角线所在直线的左侧还是 右侧。因为被对角线分割开的两三角形不相关,所以可以单独讨论:分别找出左右两侧的最大三角形,二者之和即为此边对应的最大四边形。整个算法为 O(n3)。

    3、何为叉积?

      百度百科“叉积”解释的很详细,这里用到两条:

      一、axb 表示的是一个符合右手法则的、垂直于ab的向量c,|c|=|a|*|b|*sinθ,θ指向量a,b的夹角,即|c|是以a、b为边的平行四边形的面积——已知3点A,B,C,|BAxCA|==S(三角形ABC)*2。

      二、坐标表示法中,a(x1,y1),b(x2,y2)。c=axb=x1*y2-x2*y1,c的正负表示方向,正为上、负为下。而在三维中,方向不能简单的以正负表示,所以只能以一个向量的形式来描述:

      |  i , j , k |

      |x1,y1,z1|

      |x2,y2,z2|  i,j,k分别表示x轴、y轴、z轴上的单位向量,矩阵的解也就是c=axb

      这里只是二维平面,判断点在向量所在直线的哪一侧,就可以利用叉积的方向来区别。对角线AB,两侧各取一点C、D,必然有CAxCB=-DAxDB

    注意:一开始不知道叉积的模即是三角形面积的两倍,就用axb=|a|*|b|*cosθ推S=|a|*|b|*sinθ,跑到第八组数据就超时了,纠结了好久,后来发现,原来每个三角形是在O(n3)的复杂度下求解的,多算一步就多一个O(n3),TLE的不冤T^T;

    代码:

     1 #include <iostream>
     2 #include <math.h>
     3 #include <algorithm>
     4 #include <stdio.h>
     5 #include <string.h>
     6 using namespace std;
     7 #define eps 1e-10
     8 
     9 #define maxn 310
    10 typedef struct point{
    11     double x,y;
    12 }p;
    13 p Point[maxn];
    14 
    15 double cross(point p1,point p2,point p0){
    16     return ((p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x))*0.5;
    17 }
    18 
    19 double max(double a,double b){
    20     if(a>b) return a;
    21     return b;
    22 }
    23 int main()
    24 {
    25     int n;
    26     while(~scanf("%d",&n)){
    27         for(int i=0;i<n;i++)
    28             scanf("%lf %lf",&Point[i].x,&Point[i].y);
    29         double ans=0,lmax=0,rmax;
    30         for(int i=0;i<n;i++){
    31             for(int j=i+1;j<n;j++){
    32                     rmax=0,lmax=0;
    33                     for(int k=0;k<n;k++){
    34                         if(k!=i && k!=j){
    35                             double s=cross(Point[i],Point[j],Point[k]);
    36                             if(s<eps){
    37                                 lmax=max(lmax,-s);
    38                             }
    39                             else{
    40                                 rmax=max(rmax,s);
    41                             }
    42                         }
    43                     }
    44                     if(lmax==0 || rmax==0)continue;
    45                     ans=max(ans,(rmax+lmax));
    46             }
    47         }
    48         printf("%lf
    ",ans);
    49     }
    50     return 0;
    51 }
  • 相关阅读:
    转:yum和aptget用法及区别
    APT upgrade 和 distupgrade 的差別
    flickr api 入门教程
    查看FileZila 快速连接密码
    Freemium模式
    asp.net 开发环境搭建
    flickr api authentication
    转:虚拟机VirtualBox中Ubuntu无法全屏解决方法
    转:网页设计中的默认字体样式详解
    Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
  • 原文地址:https://www.cnblogs.com/lovychen/p/3678592.html
Copyright © 2020-2023  润新知