POJ1408 两条线段求交点+叉乘求几何面积+枚举

POJ1408


1  求两条直线规范相交的交点坐标
 


如图,已知点A、B、C、D的坐标,求点P坐标:
 

 


 




其中,第一个式子不需要解释,记住这个定理即可。
第二个式子是由定比分点坐标公式推出。
     

Note①:
二维向量叉乘公式
a(x1,y1),b(x2,y2),则a×b=(x1y2-x2y1).


Note②:
定比分点坐标公式:


已知四点如图所示,其中  , , ,,在两点连线上有一点P,设它的坐标 ,

 ,可以求出P的坐标公式,如下:

 


 

 带入并化简,可得


,纵坐标   同理。


2

#include <iostream>
#include <stdio.h>
#include <math.h>
//基本思想:因为题目要求对应边的对应点相连接,所以免去了很多不必要的情况,因而才可以算出所有交点,枚举得到的所有四边形,保留最大的一个。
//关键:主要通过此题掌握,1 利用叉乘求两条规范相交直线的交点坐标 (由定比分点坐标公式和叉乘求三角形面积公式联立化简所得)(规范相交,两条直线只有一个非端点的交点,即该两条线段的四个端点分别处于交点两个方向的左右两侧) ,2 利用叉乘求多面性面积(通过三角形面积相加得到)
//注意:叉乘得面积,面积是有正负的,向量ab叉乘向量ac(向量ab是a->b,向量ac是a->c),方向是根据右手定则从ab指向ac时大拇指所指的方向,向外是正,向内是负。
using namespace std;
struct point{
    double x;
    double y;
}point[35][35];
double xx;double yy;
double Area(struct point a,struct point b,struct point c){//利用ab叉乘ac
    return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);//向量ab,即箭头为a->b,时,用点b的坐标减去a的坐标
}
void Intersection(struct point line1_A,struct point line1_B,struct point line2_C,struct point line2_D){
    double area1=Area(line1_A,line1_B,line2_D);
    double area2=Area(line1_A,line2_C,line1_B);
    xx=( area1*(line2_C.x)+area2*(line2_D.x) ) / ( area1+area2 );
    yy=( area1*(line2_C.y)+area2*(line2_D.y) ) / ( area1+area2 );

    return;
}
int main()
{
    int n;
    while(~scanf("%d",&n)&&n!=0){
        ///Ini:
        point[0][0].x=0;point[0][0].y=0;
        point[n+1][n+1].x=1;point[n+1][n+1].y=1;
        point[0][n+1].x=0;point[0][n+1].y=1;
        point[n+1][0].x=1;point[n+1][0].y=0;
        for(int i=1;i<=n;i++){
            scanf("%lf",&point[i][0].x);
            point[i][0].y=0;
        }
        for(int i=1;i<=n;i++){
            scanf("%lf",&point[i][n+1].x);
            point[i][n+1].y=1;
        }
        for(int i=1;i<=n;i++){
            scanf("%lf",&point[0][i].y);
            point[0][i].x=0;
        }
        for(int i=1;i<=n;i++){
            scanf("%lf",&point[n+1][i].y);
            point[n+1][i].x=1;
        }

        ///Intersection:
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                Intersection(point[i][0],point[i][n+1],point[0][j],point[n+1][j]);
                point[i][j].x=xx;
                point[i][j].y=yy;
                //cout<<xx<<" "<<yy<<endl;
            }
        }

        ///Enumerate:
        double maxx=0;
        double temp;
        for(int i=0;i<=n;i++){
            for(int j=0;j<=n;j++){
                temp=Area(point[i][j],point[i+1][j],point[i][j+1]);
                temp+=Area(point[i+1][j+1],point[i][j+1],point[i+1][j]);
                temp/=2;//因为四边形不一定是正方形,所以用叉乘分别算出(上三角的面积*2)和(下三角的面积*2)相加之后再/2,即可。
                if(temp>maxx){
                    maxx=temp;
                }
            }
        }

        ///printf:
        printf("%.6f\n",maxx);
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值