That Nice Euler Circuit UVALive - 3263 || 欧拉公式

欧拉定理:

简单多面体的顶点数V、棱数E及面数F间有关系有著名的欧拉公式:V-E+F=2。

设G为任意的连通的平面图,则v-e+f=2,v是G的顶点数,e是G的边数,f是G的面数。(

证明(?)

这题的做法就是模拟画线的过程,统计出画每一条线时与之前所有线的交点,将所有交点记录下来,将每一个顶点也记录下来。然后将点去重,得到点数。然后统计每一条线上有几个点,那么这条线就被分成了点数+1段,这样得到边数。最后根据公式算出面数。

  1 #include<cstdio>
  2 #include<cmath>
  3 #include<algorithm>
  4 using namespace std;
  5 namespace X
  6 {
  7     const double eps=1e-10;
  8     struct Point
  9     {
 10         double x,y;
 11         Point(double x=0,double y=0):x(x),y(y){}
 12     };
 13     typedef Point Vec;
 14     Vec operator+(const Vec& a,const Vec& b)
 15     {
 16         return Vec(a.x+b.x,a.y+b.y);
 17     }
 18     Vec operator-(const Vec& a,const Vec& b)
 19     {
 20         return Vec(a.x-b.x,a.y-b.y);
 21     }
 22     Vec operator*(const double& a,const Vec& b)
 23     {
 24         return Vec(a*b.x,a*b.y);
 25     }
 26     Vec operator*(const Vec& a,const double& b)
 27     {
 28         return Vec(b*a.x,b*a.y);
 29     }
 30     Vec operator/(const Vec& a,const double& b)
 31     {
 32         return Vec(a.x/b,a.y/b);
 33     }
 34     int dcmp(double x)
 35     //正为1,负为-1,0为0
 36     {
 37         if(fabs(x)<eps)    return 0;
 38         return x<0?-1:1;
 39     }
 40     bool operator<(const Vec& a,const Vec& b)
 41     //人为规定的优先级
 42     {
 43         return a.x<b.x||(a.x==b.x&&a.y<b.y);
 44     }
 45     bool operator==(const Vec& a,const Vec& b)
 46     //判向量相等
 47     {
 48         return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
 49     }
 50     double dot(const Vec& a,const Vec& b)
 51     //点积
 52     {
 53         return a.x*b.x+a.y*b.y;
 54     }
 55     double cross(const Vec& a,const Vec& b)
 56     //叉积
 57     {
 58         return a.x*b.y-a.y*b.x;
 59     }
 60     double len(const Vec& x)
 61     //向量长度
 62     {
 63         return sqrt(dot(x,x));
 64     }
 65     double angle(const Vec& a,const Vec& b)
 66     //夹角,0~180°
 67     {
 68         return acos(dot(a,b)/len(a)/len(b));
 69     }
 70     double angle1(const Vec& a,const Vec& b)
 71     //夹角,带方向,a到b逆时针为正,顺时针为负,共线为0
 72     {
 73         return acos(dot(a,b)/len(a)/len(b))*(dcmp(cross(a,b)));
 74     }
 75     Vec rotate(const Vec& a,const double& rad)
 76     //旋转,正为逆时针,负为顺时针
 77     {
 78         return Vec(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad));
 79     }
 80     Vec normal(const Vec& x)
 81     //单位法线,左转90°后除以自身长度
 82     {
 83         double l=len(x);
 84         return Vec(-x.y/l,x.x/l);
 85     }
 86     Vec normal1(const Vec& x)
 87     //法线,不归一化
 88     {
 89         return Vec(-x.y,x.x);
 90     }
 91     Point lineline(const Point& p,const Vec& v,const Point& q,const Vec& w)
 92     //直线交点,GetLineIntersection
 93     {
 94         return p+v*cross(w,p-q)/cross(v,w);
 95     }
 96     double ptline(const Point& p,const Point& a,const Point& b)
 97     //point_to_line,点到直线距离,DistanceToLine
 98     {
 99         Vec v1=b-a,v2=p-a;
100         return fabs(cross(v1,v2)/len(v1));
101     }
102     double ptseg(const Point& p,const Point& a,const Point& b)
103     //point_to_segment,点到线段距离,DistanceToSegment
104     {
105         if(a==b)    return len(p-a);
106         //Vec v1=b-a,v2=a-p,v3=p-b;
107         Vec v1=b-a,v2=p-a,v3=p-b;
108         if(dcmp(dot(v1,v2))<0)    return len(v2);
109         else if(dcmp(dot(v1,v3))>0)    return len(v3);
110         else return fabs(cross(v1,v2)/len(v1));
111     }
112     double area2(const Point& a,const Point& b,const Point& c)
113     //叉积对应平行四边形的面积
114     {
115         return cross(b-a,c-a);
116     }
117     double thrarea(const Point& a,const Point& b,const Point& c)
118     //三角形面积,绝对值
119     {
120         return fabs(cross(b-a,c-a)/2);
121     }
122     bool ifpar(const Vec& a,const Vec& b)
123     //ifParallel
124     //是否共线/平行
125     {
126         return dcmp(cross(a,b))==0;
127     }
128     Point pointline(const Point& p,const Point& a,const Vec& v)
129     //点在直线上投影,GetLineProjection
130     {
131         return a+v*(dot(p-a,v)/dot(v,v));
132     }
133     bool ifsegseg(const Point& a1,const Point& a2,const Point& b1,const Point& b2)
134     //SegmentProperIntersection,线段相交判定,不包含端点,不允许共线。有交点时求交点直接用直线交点即可
135     //此处就是求两条线段的两个端点是否都分别在另一条线段的两侧
136     {
137         double c1=cross(a2-a1,b1-a1),c2=cross(a2-a1,b2-a1),
138             c3=cross(b2-b1,a1-b1),c4=cross(b2-b1,a2-b1);
139         return dcmp(c1)*dcmp(c2)<0&&dcmp(c3)*dcmp(c4)<0;
140     }
141     bool ifonseg(const Point& p,const Point& a1,const Point& a2)
142     //OnSegment,点是否在线段上
143     //这样就能判定向量p a1与p a2共线,且方向相反
144     {
145         return dcmp(cross(a1-p,a2-p))==0&&dcmp(dot(a1-p,a2-p))<0;
146     }
147     bool ifsegseg1(const Point& a1,const Point& a2,const Point& b1,const Point& b2)
148     //线段相交判定,包含端点,允许共线
149     {
150         double c1=cross(a2-a1,b1-a1),c2=cross(a2-a1,b2-a1),
151             c3=cross(b2-b1,a1-b1),c4=cross(b2-b1,a2-b1);
152         return (dcmp(c1)*dcmp(c2)<0&&dcmp(c3)*dcmp(c4)<0)||
153         (dcmp(c1)==0&&dcmp(c2)==0)||ifonseg(a1,b1,b2)||
154         ifonseg(a2,b1,b2)||ifonseg(b1,a1,a2)||ifonseg(b2,a1,a2);
155     }
156     double polyarea(Point p[],int n)
157     //PolygonArea,有向面积,要求点按顺序能组成多边形(不会边相交,可以凹),如果顺时针转就是负,逆时针就是正(未验证)
158     {
159         double ans=0;
160         for(int i=1;i<n-1;i++)
161             ans+=cross(p[i]-p[0],p[i+1]-p[0]);
162         return ans/2;
163     }
164 };
165 using namespace X;
166 Point p[310];
167 Point p2[100000];
168 int n,v,e,T;
169 int main()
170 {
171     int i,j;
172     scanf("%d",&n);
173     while(n!=0)
174     {
175         v=0;e=n-1;
176         scanf("%lf%lf",&p[1].x,&p[1].y);
177         p2[++v]=p[1];
178         for(i=2;i<=n;i++)
179         {
180             scanf("%lf%lf",&p[i].x,&p[i].y);p2[++v]=p[i];
181             for(j=1;j<=i-2;j++)
182             {
183                 if(ifsegseg(p[i-1],p[i],p[j],p[j+1]))
184                     p2[++v]=lineline(p[i-1],p[i]-p[i-1],p[j],p[j+1]-p[j]);
185             }
186         }
187         sort(p2+1,p2+v+1);
188         v=unique(p2+1,p2+v+1)-p2-1;
189         for(i=1;i<n;i++)
190             for(j=1;j<=v;j++)
191                 if(ifonseg(p2[j],p[i],p[i+1]))
192                     e++;
193         printf("Case %d: There are %d pieces.\n",++T,e+2-v);
194         scanf("%d",&n);
195     }
196     return 0;
197 }
posted @ 2017-11-02 08:38  hehe_54321  阅读(230)  评论(0编辑  收藏  举报
AmazingCounters.com