题目链接:http://acm.fzu.edu.cn/problem.php?pid=2148
题意:
求给定的二维坐标能构成的凸四边形数
思路:
我们可以得到一个结论:
当且仅当四边形为凸四边形时,对角线能相交 -> 若四边形存在线段相交就是凸四边形
#include<iostream> #include<stdio.h> #include<math.h> #include<string.h> #include<algorithm> using namespace std; typedef long long ll; #define ST 1001 #define EN 1002 #define M 10000 #define inf 1000000 #define eps 1e-8 #define PR 1e-8 struct Point{//点是2维的 double x,y; }p[50]; struct v{ Point Start,End; }; double Cross(Point p1,Point p2,Point p3,Point p4){//二维向量(p1p2)X(p3p4) 返回第三向量长度 double x1=p2.x-p1.x,y1=p2.y-p1.y; double x2=p4.x-p3.x,y2=p4.y-p3.y; return x1*y2-x2*y1; //为0表示 p1p2 与p3p4共线 //直线:不为0就是相交 } double Cross_v(v v1,v v2){ return Cross(v1.Start,v1.End,v2.Start,v2.End); } double point_dis(Point p1,Point p2){ return sqrt((double)((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y))); } bool On_Segment(Point p1,Point p2,Point p3){//p3点在 p1p2线段上 if(Cross(p1,p2,p1,p3)!=0)return false; bool iny=(p1.y<=p3.y && p3.y<=p2.y)||(p1.y>=p3.y && p3.y>=p2.y); bool inx=(p1.x<=p3.x && p3.x<=p2.x)||(p1.x>=p3.x && p3.x>=p2.x); if(inx && iny)return true; return false; } bool Segmentintersect(Point p1,Point p2,Point p3,Point p4){//p1p2 是否与 p3p4相交 double cross_1=Cross(p3,p4,p3,p1),cross_2=Cross(p3,p4,p3,p2);//cross_1 2必须一正一负且都不为0 double cross_3=Cross(p1,p2,p1,p3),cross_4=Cross(p1,p2,p1,p4);//cross_2 4必须一正一负且都不为0 //表示a线段 2点 在b线段 2侧 if(cross_1*cross_2<0 && cross_3*cross_4<0)return true; //a线段端点在 b线段上 视情况取舍这种位置 // if(cross_1==0 && On_Segment(p3,p4,p1))return true; // if(cross_2==0 && On_Segment(p3,p4,p2))return true; // if(cross_3==0 && On_Segment(p1,p2,p3))return true; // if(cross_4==0 && On_Segment(p1,p2,p4))return true; return false; } int ok(Point a,Point b, Point c,Point d){ bool ans = Segmentintersect(a,b,c,d) ; ans|= Segmentintersect(a,c,b,d) ; ans|= Segmentintersect(a,d,c,b) ; return ans; } int main() { int T,Cas = 1; scanf("%d",&T); int i, j, k, l; while(T--){ int n, ans=0;scanf("%d",&n); for(i=0;i<n;i++)scanf("%lf%lf",&p[i].x,&p[i].y); for(i = 0; i < n; i++) for(j = i+1; j <n; j++) for(k = j+1;k<n;k++) for(l = k+1;l<n;l++) ans += ok(p[i],p[j],p[k],p[l]); printf("Case %d: %d\n",Cas++,ans); } return 0; } /* 99 4 0 0 100 0 0 100 100 100 4 0 0 100 0 0 100 10 10 */