题目链接: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
*/