POJ 1569 Myacm Triangles(判定点在三角形内)

POJ 1569 Myacm Triangles(判定点在三角形内)

http://poj.org/problem?id=1569

题意: ZOJ 1704

       给你n个点的坐标,要你找出面积最大的由3个点构成的三角形,且该三角形的内部或边上不能有点. 点数<=15.

分析:

       由于点数<=15,所以我们直接暴力枚举每个可能的三角形(枚举的三点首先要不共线),然后判断该三角形是否包含点. 如果不含点,那么就计算它的面积即可.

       如何判断一个点是否在一个三角形的边上或内部呢?

       方法一: 如果一个点P在三角形ABC内部(或边上),那么三角形PAB+三角形PBC+三角形PAC的面积 == ABC的面积. 否则前者面积和应该更大.

       方法二: 如果一个点P在三角形ABC内部(或边上), Cross(A-B,P-B)与Cross(B-C,P-C),与Cross(C-A,P-A) 一定要么同时>=0,要么同时<=0. (注意CrossABC三点的书写顺序不能改)

       以上两个结论自己画图验证一下最直观.

AC代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const double eps=1e-10;
int dcmp(double x)
{
    if(fabs(x)<eps) return 0;
    return x<0?-1:1;
}
const int maxn=15+5;
struct Point
{
    double x,y;
    Point(){}
    Point(double x,double y):x(x),y(y){}
}P[maxn];
typedef Point Vector;
Vector operator-(Point A,Point B)
{
    return Vector(A.x-B.x,A.y-B.y);
}
double Cross(Vector A,Vector B)
{
    return A.x*B.y-A.y*B.x;
}
double Area(Point A,Point B,Point C)
{
    return fabs(Cross(B-A,B-C))/2;
}
bool InTriangle(Point P,Point A,Point B,Point C)//判断点P是否在三角形ABC的内部(包括边上)
{
    double a1=Area(P,A,B),a2=Area(P,A,C),a3=Area(P,B,C),b=Area(A,B,C);
    return dcmp(a1+a2+a3-b)==0;
}
/*
bool InTriangle(Point P,Point A,Point B,Point C)//判断点P是否在三角形ABC的内部(包括边上)
{
    double c1=Cross(A-B,P-B),c2=Cross(B-C,P-C),c3=Cross(C-A,P-A);
    //Cross内节点顺序不能乱,一定要顺时针或逆时针
    return (dcmp(c1)>=0 && dcmp(c2)>=0 && dcmp(c3)>=0) || (dcmp(c1)<=0 && dcmp(c2)<=0 && dcmp(c3)<=0)
}
*/
bool check(int i,int j,int k,int n)//判断第i,j,k个点是否能构成一个内部无点的三角形
{
    if( dcmp(Cross(P[i]-P[j],P[i]-P[k]))==0 ) return false;//三点共线
    for(int it=0;it<n;++it)if(it!=i && it!=j && it!=k)
    {
        if(InTriangle(P[it],P[i],P[j],P[k])) return false;
    }
    return true;
}

int main()
{
    int n;
    while(scanf("%d",&n)==1 && n)
    {
        for(int i=0;i<n;++i)
        {
            char c;
            scanf(" %c %lf %lf",&c,&P[i].x,&P[i].y);
        }
        double ans=0; //最大三角形面积
        int num[3];//保存最大三角形的三个点编号
        for(int i=0;i<n;++i)
        for(int j=i+1;j<n;++j)
        for(int k=j+1;k<n;++k)
        if(check(i,j,k,n))
        {
            double area=Area(P[i],P[j],P[k]);
            if(ans<area)
            {
                ans=area;
                num[0]=i,num[1]=j,num[2]=k;
            }
        }
        printf("%c%c%c\n",num[0]+'A',num[1]+'A',num[2]+'A');
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值