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. (注意Cross内ABC三点的书写顺序不能改)
以上两个结论自己画图验证一下最直观.
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; }