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

欧拉公式:  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模板也存在这个问题)

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

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

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

4

0 0 0 1 0 2 0 0    

答案为2

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

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

poj2284 欧拉公式的更多相关文章

  1. poj2284 That Nice Euler Circuit(欧拉公式)

    题目链接:poj2284 That Nice Euler Circuit 欧拉公式:如果G是一个阶为n,边数为m且含有r个区域的连通平面图,则有恒等式:n-m+r=2. 欧拉公式的推广: 对于具有k( ...

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

                                                          That Nice Euler Circuit Time Limit: 3000MS   M ...

  3. hdu5047 找规律+欧拉公式

    题意:在一个正方形内画n个M,求最多能分成多少个平面 sol:这种求划分成多少个平面的题第一反应肯定是欧拉公式: 二维平面上的欧拉公式:V+F-E=1 (V:Vertices,F:Faces,E:Ed ...

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

    题意: 一块圆形土地,在圆周上选n个点,然后两两连线,问把这块土地分成多少块? 分析: 首先紫书上的公式是错的,不过根据书上提供的思路很容易稍加修改得到正确答案! 然后推公式吧,这里用到平面图的欧拉公 ...

  5. 几何学中的欧拉公式:V-E+F = 2

    几何学中的欧拉公式:V-E+F = 2,V.E.F表示简单几何体的顶点数.边数.面数. 证明: 它的证明有多种,这里呈现一种递归证法. 对于任意简单几何体(几何体的边界不是曲线),我们考察这个几何体的 ...

  6. HDOJ 1418 抱歉(欧拉公式)

    Problem Description 非常抱歉,本来兴冲冲地搞一场练习赛,由于我准备不足,出现很多数据的错误,现在这里换一个简单的题目: 前几天在网上查找ACM资料的时候,看到一个中学的奥数题目,就 ...

  7. D. PolandBall and Polygon BIT + 欧拉公式

    http://codeforces.com/contest/755/problem/D // 我也觉得非平面图不能用欧拉公式,但是也能过,不知道为什么.求大佬留言. 这题其实就是平面图,因为它有很多个 ...

  8. 1418 抱歉 ACM 欧拉公式

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1418 思路:一看题目,明显是要求我们找规律,于是我就在草稿纸上画了很多个图像,还是没有找到规律,于是我就在 ...

  9. 2017乌鲁木齐区域赛D题Fence Building-平面图的欧拉公式

    这个题B站上面有这题很完整的分析和证明,你实在不懂,可以看看这个视频  https://www.bilibili.com/video/av19849697?share_medium=android&a ...

随机推荐

  1. opencv 中对一个像素的rgb值或像素值进行操作的几个常用小办法【转】

    You can access the Image pixels in many ways:1. One using the Inbuilt macro2. One using the pointer ...

  2. BI的相关问题[转]

    什么是BI? Business Intelligence(BI) = Data Warehouse(DW) + OLAP + Data Mining(DM) 商业智能=数据仓库+联机分析+数据挖掘 做 ...

  3. C 语言学习的第 01 课:先来聊聊计算机吧

    各位同学,新学期,我就是你们的助教了.我的个人信息,你们的任课老师都已经介绍过了,所以我这里也就不再啰嗦.下面,来聊聊今天的话题:“先来谈谈计算机吧”. 想必看到这个题目,你们大家一定是不愿意点击进来 ...

  4. 使textarea支持tab缩进

    //textarea支持tab缩进 $("textarea").on( 'keydown', function(e) { if (e.keyCode == 9) { e.preve ...

  5. [转]Windows系统注册表知识完全揭密

    来源:http://www.jb51.net/article/3328.htm Windows注册表是帮助Windows控制硬件.软件.用户环境和Windows界面的一套数据文件,注册表包含在Wind ...

  6. XML中的DOCTYPE属性

    一.先来两个小例子 内部dtd将standalone设为真. <?xml version="1.0" standalone="yes"?> < ...

  7. linux基础-第十四单元 Linux网络原理及基础设置

    第十四单元 Linux网络原理及基础设置 三种网卡模式图 使用ifconfig命令来维护网络 ifconfig命令的功能 ifconfig命令的用法举例 使用ifup和ifdown命令启动和停止网卡 ...

  8. 【Alpha版本】冲刺阶段——Day 8

    我说的都队 031402304 陈燊 031402342 许玲玲 031402337 胡心颖 03140241 王婷婷 031402203 陈齐民 031402209 黄伟炜 031402233 郑扬 ...

  9. Eclipse导入 appcompat,design兼容包

    从Android studio推出1.0正式版后,就一直在as上开发项目,但是最近要测试一个项目,是eclipse结构,导入as后,是各种报错信息,决定改成eclipse. 其中项目中用到了ppcom ...

  10. ueditor1.3.6jsp版在struts2应用中上传图片报"未找到上传文件"解决方案

    摘要: ueditor1.3.6jsp版在struts2应用中上传图片报"未找到上传文件"解决方案 在struts2应用中使用ueditor富文本编辑器上传图片或者附件时,即使配置 ...