zoukankan      html  css  js  c++  java
  • 几何问题 poj 1408

    参考博客:

    用向量积求线段焦点证明:

    首先,我们设 (AD向量 × AC向量) 为 multi(ADC) ; 那么 S三角形ADC = multi(ADC)/2 。

    由三角形DPD1 与 三角形CPC1 相似;可得 |DP| / |PC| = |DD1| / |CC1| = multi(ADB) × multi(ACB) 。

    |DP| / |PC| = (xD - xP) / (xP - xC) = (yD - yP) / (yP - yC) 。

    xP = ((multi(D,B,A) * xC - multi(C,B,A) * xD)) / (multi(D,B,A) - multi(C,B,A));

    yP = ((multi(D,B,A) * yC - multi(C,B,A) * yD)) / (multi(D,B,A) - multi(C,B,A));

    题目不难,大致题意为:

    给定一个单位矩阵,并在每条边上面“嵌入”n个点,这样每条边共有n+2个点。将单位矩阵对面相应位置的点连接起来,构成n*n个不规则四边形。要求出这n*n个矩阵中面积的最大值。

    简单的模拟+叉积求三角形面积+不规则四边形划分成三角形求面积。

    枚举每个四边形,将每个四边形划分为2个三角形。利用三角形求面积公式计算面积。比较求出最大面积。

    那么关键点在于如何求三角形面积。

    下面提供2中方法:

    1)解析几何:

    海伦公式: S=p*(p-a)*(p-b)*(p-c)取根号,其中p=(a+b+c)/2;

    2)计算几何方法

    S=1/2*| ac向量 叉乘 ab向量|

    显然,计算几何方法更快,且精度更高(没有根号),代码也少,而且在求线段交点的过程中也会用到叉乘。一举两得

    另外在模拟的过程中,要格外小心,因为很多细节要注意。
    代码:

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<stdlib.h>
    #include<math.h>
    using namespace std;
    const int max_=40;
    typedef struct point{
       double x;
       double y;
    }point;
    point node[max_][max_];
    double det(double x1,double y1,double x2,double y2)
    {
        return x1*y2-x2*y1;
    }
    double cross(point A,point B,point P)//AB,AP的叉乘
    {
        return det(B.x-A.x,B.y-A.y,P.x-A.x,P.y-A.y);
    }
    void intersection(point A,point B,point C,point D,int i,int j)//两线段的交点坐标
    {
        double nulti1=cross(A,B,C);
        double nulti2=cross(A,B,D);
        //printf("%lfok
    ",nulti1);
        node[i][j].x=(nulti2*C.x-nulti1*D.x)/(nulti2-nulti1);
        node[i][j].y=(nulti2*C.y-nulti1*D.y)/(nulti2-nulti1);
    }
    int main()
    {
        int n;
        while(scanf("%d",&n)&&n)
        {
            node[1][1].x=0.0,node[1][1].y=1.0;
            node[1][n+2].x=1.0,node[1][n+2].y=1.0;
            node[n+2][1].x=0.0,node[n+2][1].y=0.0;
            node[n+2][n+2].x=1.0,node[n+2][n+2].y=0.0;
            for(int i=2;i<=n+1;i++)
            {
                scanf("%lf",&node[n+2][i].x);
                node[n+2][i].y=0.0;
            }
            for(int i=2;i<=n+1;i++)
            {
                scanf("%lf",&node[1][i].x);
                node[1][i].y=1.0;
            }
            for(int i=n+1;i>=2;i--)
            {
                scanf("%lf",&node[i][1].y);
                node[i][1].x=0.0;
            }
            for(int i=n+1;i>=2;i--)
            {
                scanf("%lf",&node[i][n+2].y);
                node[i][n+2].x=1.0;
            }
            for(int i=2;i<=n+1;i++)
                for(int j=2;j<=n+1;j++)
            {
                intersection(node[i][1],node[i][n+2],node[1][j],node[n+2][j],i,j);
            }
            double maxm=-1.0;
            for(int i=1;i<=n+1;i++)
                for(int j=1;j<=n+1;j++)//两三角形面积和
            {
                double temp=fabs(cross(node[i][j],node[i+1][j],node[i][j+1]))*0.5+
                            fabs(cross(node[i+1][j+1],node[i+1][j],node[i][j+1]))*0.5;
                            if(maxm<temp)
                                maxm=temp;
                           //     printf("ok
    ");
            }
            printf("%.6lf
    ",maxm);
           /* for(int i=2;i<=n+1;i++){
                for(int j=2;j<=n+1;j++)
                printf("%lf ",node[i][j].x);
                printf("
    ");
            }*/
        }
    }
  • 相关阅读:
    初识DataGridView 表格数据控件
    数据适配:DataAdapter对象概述
    数据适配 DataAdapter对象
    DataSet常用简单方法
    数据集DataSet
    DateReader读取数据
    Command操作数据
    【bzoj3886】[Usaco2015 Jan]Moovie Mooving 状态压缩dp+二分
    【bzoj1572】[Usaco2009 Open]工作安排Job 贪心+堆
    【bzoj1593】[Usaco2008 Feb]Hotel 旅馆 线段树区间合并
  • 原文地址:https://www.cnblogs.com/linhaitai/p/9818208.html
Copyright © 2011-2022 走看看