欧拉定理:V+F-E=2
V的求法:将原有的拐点、线段不在端点处的的交点同一排序、去重,留下的点数就是V
E的求法:原有线段数+新被分割出的,枚举点和线段,若点在线段上,新被分割出的就多一条
注意:eps设为1e-13挂了,设为1e-10就AC
虽然A了但其实是有问题的
比如(3.333333333333333,6.0000000)
与 (3.333333333333333,7.0000000)
与 (3.333333333333334,6.0000000)
若eps设为1e-10,第三个点就被第一个点消掉了
但eps太小,可能算点积和叉积的误差不能被忽略。。。
精度坑死人呐
代码
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define eps 1e-13
struct Point
{
double x,y;
Point()
{
x=y=0;
}
};
typedef Point Vector;
Point P[305],V[100005];
Vector operator + (Vector a,Vector b)
{
a.x+=b.x;
a.y+=b.y;
return a;
}
Vector operator - (Vector a,Vector b)
{
a.x-=b.x;
a.y-=b.y;
return a;
}
Vector operator * (Vector a,double b)
{
a.x*=b;
a.y*=b;
return a;
}
int dcmp(double x)
{
if(x<=eps&&x>=-eps) return 0;
if(x>0) return 1;
return -1;
}
bool operator ==(Point a,Point b)
{
return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0;
}
bool operator < (Point a,Point b)
{
return dcmp(a.x-b.x)==-1 || (dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==-1);
}
bool operator > (Point a,Point b)
{
return dcmp(a.x-b.x)==1 || (dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==1);
}
double Dot(Vector a,Vector b)
{
return a.x*b.x+a.y*b.y;
}
double Cross(Vector a,Vector b)
{
return a.x*b.y-b.x*a.y;
}
bool jiao(Point a,Point b,Point c,Point d)
{
double c1=Cross(b-a,c-a),c2=Cross(b-a,d-a),c3=Cross(d-c,a-c),c4=Cross(d-c,b-c);
return dcmp(c1)*dcmp(c2)<0&&dcmp(c3)*dcmp(c4)<0;
}
Point jiaodian(Point P,Vector v,Point Q,Vector w)
{
Vector u=P-Q;
double t=Cross(w,u)/Cross(v,w);
return P+v*t;
}
bool PointOnLine(Point p,Point a,Point b)
{
return dcmp(Cross(p-a,p-b))==0 && dcmp(Dot(p-a,p-b))==-1;
}
void jh(Point& a,Point& b)
{
Point t=a;
a=b;
b=t;
}
void kp(int low,int high)
{
int i=low,j=high;
Point mid=V[(i+j)/2];
while(i<j)
{
while(V[i]<mid) i++;
while(V[j]>mid) j--;
if(i<=j)
{
jh(V[i],V[j]);
i++;
j--;
}
}
if(j>low) kp(low,j);
if(i<high) kp(i,high);
}
int main()
{
int T=0,n,i,j,v,e;
while(scanf("%d",&n)&&n>0)
{
T++;
for(i=1;i<=n;i++)
{
scanf("%lf%lf",&P[i].x,&P[i].y);
V[i]=P[i];
}
v=e=n-1;
for(i=1;i<n-1;i++)
for(j=i+1;j<n;j++)
if(jiao(P[i],P[i+1],P[j],P[j+1])) V[++v]=jiaodian(P[i],P[i+1]-P[i],P[j],P[j+1]-P[j]);
kp(1,v);
j=0;
for(i=1;i<=v;i++)
if(i==1||!(V[i]==V[i-1])) V[++j]=V[i];
v=j;
for(i=1;i<=v;i++)
for(j=1;j<n;j++)
if(PointOnLine(V[i],P[j],P[j+1])) e++;
printf("Case %d: There are %d pieces.\n",T,e-v+2);
}
return 0;
}