poj2284 欧拉公式

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

欧拉公式:  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 }

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

4

0 0 0 1 0 2 0 0    

答案为2

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

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

时间: 2024-10-10 09:44:48

poj2284 欧拉公式的相关文章

poj2284 That Nice Euler Circuit(欧拉公式)

题目链接:poj2284 That Nice Euler Circuit 欧拉公式:如果G是一个阶为n,边数为m且含有r个区域的连通平面图,则有恒等式:n-m+r=2. 欧拉公式的推广: 对于具有k(k≥2)个连通分支的平面图G,有:n-m+r=k+1. 题意:给出连通平面图的各顶点,求这个欧拉回路将平面分成多少区域. 题解:根据平面图的欧拉定理“n-m+r=2”来求解区域数r. 顶点个数n:两两线段求交点,每个交点都是图中的顶点. 边数m:在求交点时判断每个交点落在第几条边上,如果一个交点落在

POJ2284 That Nice Euler Circuit (欧拉公式)(计算几何 线段相交问题)

That Nice Euler Circuit Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 1977   Accepted: 626 Description Little Joey invented a scrabble machine that he called Euler, after the great mathematician. In his primary school Joey heard about

uva 10213 How Many Pieces of Land (欧拉公式计算多面体)

题意:在一个圆上取n个点,求最多能将圆分为多少块: 思路:欧拉公式计算多面体: 欧拉公式:简单多面体的顶点数V.面数F及棱数E之间的关系为V+F-E=2; 首先考虑点数v,有n个在圆上的点,任取一点x,考虑与x相连的每条对角线,假设对角线左边有i个顶点,则右边应有(n-2-i)个顶点,这些顶点相互连接可以产生i*(n-i-2)个顶点,再将所有的x与所有的对角线l求和.每个交点分别算了4次(一个交点由两条线产生,有4个圆上的点会计算到),除以4: V=n+n/4*(西格玛i=1到n-3) i*(n

世界的本质是旋转(1)复平面与欧拉公式

最近闲来无事,翻看起旧课本<信号与系统>,不经意间对一些基础问题有了新的理解角度.在上学的时候,我搞不清楚,这傅里叶变换是毛?明明一个时域波形,非要搞出个频率出来,虽然很好用,但是看不见摸不着的,实在让人头大. 1.欧拉公式 ejθ=cosθ+jsinθ 复平面上对角度取复指数,被定义为单位圆上角度为θ的向量,亦可理解为单位向量"1"沿逆时针从X+轴旋转θ度后的结果. cosθ 是横坐标,sinθ 是纵坐标,通过因子 j 与实坐标组合起来,表示一个确切的位置. 当然,通过一

hdu5047 找规律+欧拉公式

题意:在一个正方形内画n个M,求最多能分成多少个平面 sol:这种求划分成多少个平面的题第一反应肯定是欧拉公式: 二维平面上的欧拉公式:V+F-E=1 (V:Vertices,F:Faces,E:Edges) 然后我们画出三个M的情况看一下:(果然Pad是个画图神器..去年网赛的时候光画图就画了半天...) 最多的情况就是每两个M都相交 先分析vertices:两个M相交共16个交点,再加上每个M和正方形相交又有2个交点. 所以加起来就是V=16*C(n,2)+2*n=8*n*n-6n 再来看e

UVa 10213 (欧拉公式+Java大数) How Many Pieces of Land ?

题意: 一块圆形土地,在圆周上选n个点,然后两两连线,问把这块土地分成多少块? 分析: 首先紫书上的公式是错的,不过根据书上提供的思路很容易稍加修改得到正确答案! 然后推公式吧,这里用到平面图的欧拉公式,V - E + F = 2,其中V表示顶点个数,E表示边的个数,F表示面的块数. 减去最外面的无限大的面,所求ans = E - V + 1 假设n≥4,从圆周上的一个点出发枚举一条对角线,左边有i个点,右边有n-2-i个点,将左右两边的点两两相连,就在这条对角线上得到个交点.每个交点被重复计算

ZOJ--3574--Under Attack II【线段树+欧拉公式】

链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3574 题意:一个坐标系,给出x1.x2限定左右边界,有n条直线,告诉每条直线的k和b,问在x1.x2区间内空间被直线分割成几部分 思路: 这道题是比赛时做的,AC之后发现别人都是用归并排序求逆序对数来解的. 说我的解法吧,首先拿到题的时候发现是划分区域这样的,第一下就想到了欧拉公式,但是n有30000,n^2找交点肯定要超时.土豪在纸上画了一下,一条直线必然在x1和

点、边、面——欧拉公式

题目描述: 原理:欧拉公式 具体细节:顶点数和边数 //多少块土地 #include<iostream> using namespace std; int main() { int n; cin >> n; int v, e, f; //欧拉公式 V-E+F=2 int v0 = 0, e0 = 0; for(int i = 0; i <= n-2; i++) { v0 += i * (n - 2 - i); e0 += i * (n - 2 - i) + 1; } v =

欧拉公式

LRJ算法入门经典第二版上面写错了,害得我想了半天... V : 点数, E :边数  F :面数 欧拉公式 V - E + F = 2: V =  n + n / 4 sum(i * (n - 2 - i));  [ 0 <= i <= n - 2]; E = n + n / 2 sum((i * (n - 2 - i ) + 1); [ 0 <= i <= n - 2]; 代码实现: #include<cstdio> #include<cstring>