码迷,mamicode.com
首页 > 其他好文 > 详细

poj2284 欧拉公式

时间:2015-01-29 17:23:31      阅读:125      评论:0      收藏:0      [点我收藏+]

标签:

题意:给出一图形,求该图形把平面分成了几部分

 

欧拉公式:  http://blog.csdn.net/wangxiaojun911/article/details/4586550

对于二维平面上的情况。设图形上有V个点,E条边,把平面分成了F个独立的部分,那么满足V+F-E=2

如下图:

技术分享             技术分享

 

 

那么求F就转化成了如何求V和E

求V:枚举任意两线段的交点即可。注意可能出现三线共点的情况,要判重。

求E:某线段上的n个点会把这条线段分成n-1部分。用这个性质再YY一下就好了。

 

注意:

1.这里判重不能用map,因为交点的计算结果肯定是有精度误差的,再hash一下就没法判重了。

  我用的方法是手艹了一个破vector,实际上有更简洁的方法.....

     先排序,使重复的元素在数组里相邻。再用STL里的unique即可轻松实现去重

     ( Reference:http://blog.sina.com.cn/s/blog_a389f34a01013itn.html)

 

2.模板里的求两线段交点代码没有考虑这种情况:

技术分享

如图,两线段分别为【(0,0)->(0,1)】和【(0,1)->(0,2)】

模板代码认为他们是不香蕉的= =  哼

所以这里要处理一下:

(大白书上lrj模板也存在这个问题)

    //求两线交点
    point crosspoint(line v)
    {
        if ((point_cmp(a,v.a))||(point_cmp(a,v.b)))     return a;
        if ((point_cmp(b,v.a))||(point_cmp(b,v.b)))     return b;        //处理端点处相交的情况
        double a1=v.b.sub(v.a).det(a.sub(v.a));
        double a2=v.b.sub(v.a).det(b.sub(v.a));
        return point((a.x*a2-b.x*a1)/(a2-a1),(a.y*a2-b.y*a1)/(a2-a1));
    }

 

 

AC  Code:

技术分享
  1 #include<vector>
  2 #include<list>
  3 #include<map>
  4 #include<set>
  5 #include<deque>
  6 #include<queue>
  7 #include<stack>
  8 #include<bitset>
  9 #include<algorithm>
 10 #include<functional>
 11 #include<numeric>
 12 #include<utility>
 13 #include<iostream>
 14 #include<sstream>
 15 #include<iomanip>
 16 #include<cstdio>
 17 #include<cmath>
 18 #include<cstdlib>
 19 #include<cctype>
 20 #include<string>
 21 #include<cstring>
 22 #include<cstdio>
 23 #include<cmath>
 24 #include<cstdlib>
 25 #include<ctime>
 26 #include<climits>
 27 #include<complex>
 28 #define mp make_pair
 29 #define pb push_back
 30 using namespace std;
 31 const double eps=1e-8;//精度
 32 const double pi=acos(-1.0);//π
 33 const double inf=1e20;//无穷大
 34 const int maxp=1111;//最大点数
 35 /*
 36     判断d是否在精度内等于0
 37 */
 38 int dblcmp(double d)
 39 {
 40     if (fabs(d)<eps)return 0;
 41     return d>eps?1:-1;
 42 }
 43 
 44 
 45 bool dcmp(double x)
 46 {
 47     return (fabs(x)<eps);
 48 }
 49 
 50 /*
 51     求x的平方
 52 */
 53 inline double sqr(double x){return x*x;}
 54 /*
 55     点/向量
 56 */
 57 struct point
 58 {
 59     double x,y;
 60     point(){}
 61     point(double _x,double _y):x(_x),y(_y){};
 62     //读入一个点
 63     void input()
 64     {
 65         scanf("%lf%lf",&x,&y);
 66     }
 67     //输出一个点
 68     void output()
 69     {
 70         printf("%.2f %.2f\n",x,y);
 71     }
 72     //判断两点是否相等
 73     bool operator==(point a)const
 74     {
 75         return dblcmp(a.x-x)==0&&dblcmp(a.y-y)==0;
 76     }
 77     //判断两点大小
 78     bool operator<(point a)const
 79     {
 80         return dblcmp(a.x-x)==0?dblcmp(y-a.y)<0:x<a.x;
 81     }
 82     //点到源点的距离/向量的长度
 83     double len()
 84     {
 85         return hypot(x,y);
 86     }
 87     //点到源点距离的平方
 88     double len2()
 89     {
 90         return x*x+y*y;
 91     }
 92     //两点间的距离
 93     double distance(point p)
 94     {
 95         return hypot(x-p.x,y-p.y);
 96     }
 97     //向量加
 98     point add(point p)
 99     {
100         return point(x+p.x,y+p.y);
101     }
102     //向量减
103     point sub(point p)
104     {
105         return point(x-p.x,y-p.y);
106     }
107     //向量乘
108     point mul(double b)
109     {
110         return point(x*b,y*b);
111     }
112     //向量除
113     point div(double b)
114     {
115         return point(x/b,y/b);
116     }
117     //点乘
118     double dot(point p)
119     {
120         return x*p.x+y*p.y;
121     }
122     //叉乘
123     double det(point p)
124     {
125         return x*p.y-y*p.x;
126     }
127     //XXXXXXX
128     double rad(point a,point b)
129     {
130         point p=*this;
131         return fabs(atan2(fabs(a.sub(p).det(b.sub(p))),a.sub(p).dot(b.sub(p))));
132     }
133     //截取长度r
134     point trunc(double r)
135     {
136         double l=len();
137         if (!dblcmp(l))return *this;
138         r/=l;
139         return point(x*r,y*r);
140     }
141     //左转90度
142     point rotleft()
143     {
144         return point(-y,x);
145     }
146     //右转90度
147     point rotright()
148     {
149         return point(y,-x);
150     }
151     //绕点p逆时针旋转angle角度
152     point rotate(point p,double angle)
153     {
154         point v=this->sub(p);
155         double c=cos(angle),s=sin(angle);
156         return point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c);
157     }
158 };
159 
160 bool point_cmp(point a,point b)
161 {
162     return ((dcmp(a.x-b.x))&&(dcmp(a.y-b.y)));
163 }
164 
165 /*
166     线段/直线
167 */
168 struct line
169 {
170     point a,b;
171     line(){}
172     line(point _a,point _b)
173     {
174         a=_a;
175         b=_b;
176     }
177     //判断线段相等
178     bool operator==(line v)
179     {
180         return (a==v.a)&&(b==v.b);
181     }
182     //点p做倾斜角为angle的射线
183     line(point p,double angle)
184     {
185         a=p;
186         if (dblcmp(angle-pi/2)==0)
187         {
188             b=a.add(point(0,1));
189         }
190         else
191         {
192             b=a.add(point(1,tan(angle)));
193         }
194     }
195     //直线一般式ax+by+c=0
196     line(double _a,double _b,double _c)
197     {
198         if (dblcmp(_a)==0)
199         {
200             a=point(0,-_c/_b);
201             b=point(1,-_c/_b);
202         }
203         else if (dblcmp(_b)==0)
204         {
205             a=point(-_c/_a,0);
206             b=point(-_c/_a,1);
207         }
208         else
209         {
210             a=point(0,-_c/_b);
211             b=point(1,(-_c-_a)/_b);
212         }
213     }
214     //读入一个线段
215     void input()
216     {
217         a.input();
218         b.input();
219     }
220     //校准线段两点
221     void adjust()
222     {
223         if (b<a)swap(a,b);
224     }
225     //线段长度
226     double length()
227     {
228         return a.distance(b);
229     }
230     //直线倾斜角 0<=angle<180
231     double angle()
232     {
233         double k=atan2(b.y-a.y,b.x-a.x);
234         if (dblcmp(k)<0)k+=pi;
235         if (dblcmp(k-pi)==0)k-=pi;
236         return k;
237     }
238     //点和线段关系
239     //1 在逆时针
240     //2 在顺时针
241     //3 平行
242     int relation(point p)
243     {
244         int c=dblcmp(p.sub(a).det(b.sub(a)));
245         if (c<0)return 1;
246         if (c>0)return 2;
247         return 3;
248     }
249     //点是否在线段上
250     bool pointonseg(point p)
251     {
252         //if ((p==a) || (p==b))  return true;
253         return dblcmp(p.sub(a).det(b.sub(a)))==0&&dblcmp(p.sub(a).dot(p.sub(b)))<=0;
254     }
255     //两线是否平行
256     bool parallel(line v)
257     {
258         return dblcmp(b.sub(a).det(v.b.sub(v.a)))==0;
259     }
260     //线段和线段关系
261     //0 不相交
262     //1 非规范相交
263     //2 规范相交
264     int segcrossseg(line v)
265     {
266         int d1=dblcmp(b.sub(a).det(v.a.sub(a)));
267         int d2=dblcmp(b.sub(a).det(v.b.sub(a)));
268         int d3=dblcmp(v.b.sub(v.a).det(a.sub(v.a)));
269         int d4=dblcmp(v.b.sub(v.a).det(b.sub(v.a)));
270         if ((d1^d2)==-2&&(d3^d4)==-2)return 2;
271         return (d1==0&&dblcmp(v.a.sub(a).dot(v.a.sub(b)))<=0||
272                 d2==0&&dblcmp(v.b.sub(a).dot(v.b.sub(b)))<=0||
273                 d3==0&&dblcmp(a.sub(v.a).dot(a.sub(v.b)))<=0||
274                 d4==0&&dblcmp(b.sub(v.a).dot(b.sub(v.b)))<=0);
275     }
276     //线段和直线v关系
277     int linecrossseg(line v)//*this seg v line
278     {
279         int d1=dblcmp(b.sub(a).det(v.a.sub(a)));
280         int d2=dblcmp(b.sub(a).det(v.b.sub(a)));
281         if ((d1^d2)==-2)return 2;
282         return (d1==0||d2==0);
283     }
284     //直线和直线关系
285     //0 平行
286     //1 重合
287     //2 相交
288     int linecrossline(line v)
289     {
290         if ((*this).parallel(v))
291         {
292             return v.relation(a)==3;
293         }
294         return 2;
295     }
296     //求两线交点
297     point crosspoint(line v)
298     {
299         if ((point_cmp(a,v.a))||(point_cmp(a,v.b)))     return a;
300         if ((point_cmp(b,v.a))||(point_cmp(b,v.b)))     return b;
301         double a1=v.b.sub(v.a).det(a.sub(v.a));
302         double a2=v.b.sub(v.a).det(b.sub(v.a));
303         return point((a.x*a2-b.x*a1)/(a2-a1),(a.y*a2-b.y*a1)/(a2-a1));
304     }
305 
306     //点p到直线的距离
307     double dispointtoline(point p)
308     {
309         return fabs(p.sub(a).det(b.sub(a)))/length();
310     }
311     //点p到线段的距离
312     double dispointtoseg(point p)
313     {
314         if (dblcmp(p.sub(b).dot(a.sub(b)))<0||dblcmp(p.sub(a).dot(b.sub(a)))<0)
315         {
316             return min(p.distance(a),p.distance(b));
317         }
318         return dispointtoline(p);
319     }
320     //XXXXXXXX
321     point lineprog(point p)
322     {
323         return a.add(b.sub(a).mul(b.sub(a).dot(p.sub(a))/b.sub(a).len2()));
324     }
325     //点p关于直线的对称点
326     point symmetrypoint(point p)
327     {
328         point q=lineprog(p);
329         return point(2*q.x-p.x,2*q.y-p.y);
330     }
331 };
332 
333 
334 struct point P[1000];
335 struct line  L[1000];
336 int n;
337 int CASE=0;
338 
339 int main()
340 {
341     //freopen("in.txt","r",stdin);
342 
343     while (cin>>n)
344     {
345         if (n==0)   break;
346         {
347             CASE++;
348             n--;
349             for (int i=1;i<=n+1;i++)
350             {
351                 scanf("%lf%lf",&P[i].x,&P[i].y);
352                 if (i>=2)
353                     L[i-1]=line(point(P[i-1].x,P[i-1].y),point(P[i].x,P[i].y));
354             }
355             //L[1..n]:line      P[1..n]:point   P[1]==P[n+1]
356 
357             vector<point> POINT;
358             POINT.clear();
359 
360             int pcount=0;       //the number of points
361             for (int i=1;i<n;i++)
362                 for (int j=i+1;j<=n;j++)
363                 {
364                     if (L[i].segcrossseg(L[j])!=0)
365                     {
366                         point tm=L[i].crosspoint(L[j]);
367                         //printf("P:   %.3f   %.3f\n",tm.x,tm.y);
368                         bool Find=false;
369                         for (vector<point>::iterator it=POINT.begin();it!=POINT.end();it++)
370                         {
371                             point tp=*it;
372                             if ((dcmp(tp.x-tm.x))&&(dcmp(tp.y-tm.y)))
373                                 Find=true;
374                         }
375                         if (!Find)
376                         {
377                             pcount++;
378                             POINT.push_back(tm);
379                         }
380                     }
381                 }
382 
383             for (vector<point>::iterator it=POINT.begin();it!=POINT.end();it++)
384             {
385                 point tp=*it;
386                 //printf("%.5f %.5f\n",tp.x,tp.y);
387             }
388 
389             int lcount=0;
390             for (int i=1;i<=n;i++)
391             {
392                 line tm=L[i];
393                 int tmp=0;
394                 for (vector<point>::iterator it=POINT.begin();it!=POINT.end();it++)
395                 {
396                     point tp=*it;
397                     if (tm.pointonseg(tp))
398                         tmp++;
399                 }
400                 lcount=lcount+(tmp-1);
401             }
402 
403             //cout<<pcount<<"   "<<lcount<<endl;
404             //cout<<2+lcount-pcount<<endl;
405             //Case 1: There are 2 pieces.
406             int ans=2+lcount-pcount;
407             //if (ans<0)  ans=2;
408             printf("Case %d: There are %d pieces.\n",CASE,ans);
409         }
410     }
411 
412 
413     return 0;
414 }
View Code

 

 

PS:在poj discussion里面有人给出了这样一组数据:

4

0 0 0 1 0 2 0 0    

答案为2

这组数据我过不去 ╮(╯▽╰)╭

不过这种情况本身就够坑的,所以也不影响AC啦 ╮(╯▽╰)╭

poj2284 欧拉公式

标签:

原文地址:http://www.cnblogs.com/pdev/p/4260238.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!