Shoring Up the Levees HDU - 3103 (已知坐标求三角形各种东西)

The tiny country of Waterlogged is protected by a series of levees that form a quadrilateral as shown below: 
 



The quadrilateral is defined by four vertices. The levees partition the country into four quadrants. Each quadrant is identified by a pair of vertices representing the outside edge of that quadrant. For example, Quadrant 1 shown below is defined by the points (x1, y1) and (x2, y2) . 
 



It happens very often that the country of Waterlogged becomes flooded, and the levees need to be reinforced, but their country is poor and they have limited resources. They would like to be able to reinforce those levees that encompass the largest area first, then the next largest second, then the next largest third, and the smallest area fourth. 

Help Waterlogged identify which quadrants are the largest, and the length of the levees around them.

Input

here will be several sets of input. Each set will consist of eight real numbers, on a single line. Those numbers will represent, in order: 


X1 Y1 X2 Y2 X3 Y3 X4 Y4 


The four points are guaranteed to form a convex quadrilateral when taken in order -- that is, there will be no concavities, and no lines crossing. Every number will be in the range from -1000.0 to 1000.0 inclusive. No Quadrant will have an area or a perimeter smaller than 0.001. End of the input will be a line with eight 0.0's.

Output

For each input set, print a single line with eight floating point numbers. These represent the areas and perimeters of the four Quadrants, like this: 


A1 P1 A2 P2 A3 P3 A4 P4 


Print them in order from largest area to smallest -- so A1 is the largest area. If two Quadrants have the same area when rounded to 3 decimal places, output the one with the largest perimeter first. Print all values with 3 decimal places of precision (rounded). Print spaces between numbers. Do not print any blank lines between outputs.

Sample Input

1 2 1 5 5 2 2 0
3.5 2.2 4.8 -9.6 -1.2 -4.4 -8.9 12.4
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0

Sample Output

5.100 11.459 3.400 9.045 0.900 6.659 0.600 4.876
44.548 38.972 21.982 25.997 20.342 38.374 10.038 19.043

题意:给你四个点的坐标,他们组成的四边形的对角线的交点与其他点组三角形,如上图2,按从大到小输出三角形的面积和周长,面积一样时先输出周长长的。

这就是个水题,我记了三角形三个点坐标求面积的公式,然后在模板里找到了两直线求交点的公式,我看完后就开始要电脑,等了挺久10分钟打完,然后居然wa了/喷血,肯定没打错那就是精度问题。剩最后10分钟改下交下还是没过,队友一直刚的一题也没过= =。现在发现这题居然是要在保留三位小数后再进行比较排序。!@#¥%……&*();公式在代码里标注了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <math.h>
#include <queue>
#include <map>
#include <set>
#include <string>
#include <algorithm>
#include <vector>
#include <functional>
using namespace std;
#define MA 140000
#define ll long long
const int inf=0x3f3f3f3f;
double e=1e-8;
//const long long llinf=9e19;
struct xxx //存坐标
{
    double x,y;
};
xxx a,b,c,d,f;
struct yyy//存值
{
    double s,l;
} s[10];
double re(xxx a1,xxx a2,xxx a3)//已知三点坐标求面积公式
{
    return 0.5*fabs(a1.x*a2.y-a2.x*a1.y+a2.x*a3.y-a3.x*a2.y+a3.x*a1.y-a3.y*a1.x);
}
double chang(double x,double y,double x2,double y2)//两点间距离公式
{
    return sqrt((x-x2)*(x-x2)+(y-y2)*(y-y2));
}
double ra(xxx a1,xxx a2,xxx a3)//周长
{
    return chang(a1.x,a1.y,a2.x,a2.y)+chang(a2.x,a2.y,a3.x,a3.y)+chang(a1.x,a1.y,a3.x,a3.y);
}
bool cmp(yyy a,yyy b)//比较
{
    if(floor(a.s)==floor(b.s))//保留三位小数后比较
        return a.l>b.l;
    return a.s>b.s;
}
int main()
{
    while(~scanf("%lf %lf %lf %lf %lf %lf %lf %lf",&a.x,&a.y,&c.x,&c.y,&b.x,&b.y,&d.x,&d.y))
    {
        if(a.x==0&&a.y==0&&b.x==0&&b.y==0&&c.x==0&&c.y==0&&d.x==0&&d.y==0)
            break;
        memset(s,0,sizeof(s));
        
        double a1=(a.x-b.x)*(c.y-b.y)-(a.y-b.y)*(c.x-b.x);
        double a2=(a.x-b.x)*(d.y-b.y)-(a.y-b.y)*(d.x-b.x);
        f.x=(c.x*a2-d.x*a1)/(a2-a1);
        f.y=(c.y*a2-d.y*a1)/(a2-a1);
        //上面是求两直线的交点公式
        s[1].s=re(a,c,f)*1000;
        s[2].s=re(a,d,f)*1000;
        s[3].s=re(c,b,f)*1000;
        s[4].s=re(b,d,f)*1000;
        s[1].l=ra(a,c,f)*1000;
        s[2].l=ra(a,d,f)*1000;
        s[3].l=ra(c,b,f)*1000;
        s[4].l=ra(b,d,f)*1000;
        sort(s+1,s+5,cmp);
        for(int i=1; i<=4; i++)
        {
            printf("%.3lf %.3lf",s[i].s/1000,s[i].l/1000);
            if(i!=4)
                printf(" ");
        }
        printf("\n");
    }
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值