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:
- #include<vector>
- #include<list>
- #include<map>
- #include<set>
- #include<deque>
- #include<queue>
- #include<stack>
- #include<bitset>
- #include<algorithm>
- #include<functional>
- #include<numeric>
- #include<utility>
- #include<iostream>
- #include<sstream>
- #include<iomanip>
- #include<cstdio>
- #include<cmath>
- #include<cstdlib>
- #include<cctype>
- #include<string>
- #include<cstring>
- #include<cstdio>
- #include<cmath>
- #include<cstdlib>
- #include<ctime>
- #include<climits>
- #include<complex>
- #define mp make_pair
- #define pb push_back
- using namespace std;
- const double eps=1e-;//精度
- const double pi=acos(-1.0);//π
- const double inf=1e20;//无穷大
- const int maxp=;//最大点数
- /*
- 判断d是否在精度内等于0
- */
- int dblcmp(double d)
- {
- if (fabs(d)<eps)return ;
- return d>eps?:-;
- }
- bool dcmp(double x)
- {
- return (fabs(x)<eps);
- }
- /*
- 求x的平方
- */
- inline double sqr(double x){return x*x;}
- /*
- 点/向量
- */
- struct point
- {
- double x,y;
- point(){}
- point(double _x,double _y):x(_x),y(_y){};
- //读入一个点
- void input()
- {
- scanf("%lf%lf",&x,&y);
- }
- //输出一个点
- void output()
- {
- printf("%.2f %.2f\n",x,y);
- }
- //判断两点是否相等
- bool operator==(point a)const
- {
- return dblcmp(a.x-x)==&&dblcmp(a.y-y)==;
- }
- //判断两点大小
- bool operator<(point a)const
- {
- return dblcmp(a.x-x)==?dblcmp(y-a.y)<:x<a.x;
- }
- //点到源点的距离/向量的长度
- double len()
- {
- return hypot(x,y);
- }
- //点到源点距离的平方
- double len2()
- {
- return x*x+y*y;
- }
- //两点间的距离
- double distance(point p)
- {
- return hypot(x-p.x,y-p.y);
- }
- //向量加
- point add(point p)
- {
- return point(x+p.x,y+p.y);
- }
- //向量减
- point sub(point p)
- {
- return point(x-p.x,y-p.y);
- }
- //向量乘
- point mul(double b)
- {
- return point(x*b,y*b);
- }
- //向量除
- point div(double b)
- {
- return point(x/b,y/b);
- }
- //点乘
- double dot(point p)
- {
- return x*p.x+y*p.y;
- }
- //叉乘
- double det(point p)
- {
- return x*p.y-y*p.x;
- }
- //XXXXXXX
- double rad(point a,point b)
- {
- point p=*this;
- return fabs(atan2(fabs(a.sub(p).det(b.sub(p))),a.sub(p).dot(b.sub(p))));
- }
- //截取长度r
- point trunc(double r)
- {
- double l=len();
- if (!dblcmp(l))return *this;
- r/=l;
- return point(x*r,y*r);
- }
- //左转90度
- point rotleft()
- {
- return point(-y,x);
- }
- //右转90度
- point rotright()
- {
- return point(y,-x);
- }
- //绕点p逆时针旋转angle角度
- point rotate(point p,double angle)
- {
- point v=this->sub(p);
- double c=cos(angle),s=sin(angle);
- return point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c);
- }
- };
- bool point_cmp(point a,point b)
- {
- return ((dcmp(a.x-b.x))&&(dcmp(a.y-b.y)));
- }
- /*
- 线段/直线
- */
- struct line
- {
- point a,b;
- line(){}
- line(point _a,point _b)
- {
- a=_a;
- b=_b;
- }
- //判断线段相等
- bool operator==(line v)
- {
- return (a==v.a)&&(b==v.b);
- }
- //点p做倾斜角为angle的射线
- line(point p,double angle)
- {
- a=p;
- if (dblcmp(angle-pi/)==)
- {
- b=a.add(point(,));
- }
- else
- {
- b=a.add(point(,tan(angle)));
- }
- }
- //直线一般式ax+by+c=0
- line(double _a,double _b,double _c)
- {
- if (dblcmp(_a)==)
- {
- a=point(,-_c/_b);
- b=point(,-_c/_b);
- }
- else if (dblcmp(_b)==)
- {
- a=point(-_c/_a,);
- b=point(-_c/_a,);
- }
- else
- {
- a=point(,-_c/_b);
- b=point(,(-_c-_a)/_b);
- }
- }
- //读入一个线段
- void input()
- {
- a.input();
- b.input();
- }
- //校准线段两点
- void adjust()
- {
- if (b<a)swap(a,b);
- }
- //线段长度
- double length()
- {
- return a.distance(b);
- }
- //直线倾斜角 0<=angle<180
- double angle()
- {
- double k=atan2(b.y-a.y,b.x-a.x);
- if (dblcmp(k)<)k+=pi;
- if (dblcmp(k-pi)==)k-=pi;
- return k;
- }
- //点和线段关系
- //1 在逆时针
- //2 在顺时针
- //3 平行
- int relation(point p)
- {
- int c=dblcmp(p.sub(a).det(b.sub(a)));
- if (c<)return ;
- if (c>)return ;
- return ;
- }
- //点是否在线段上
- bool pointonseg(point p)
- {
- //if ((p==a) || (p==b)) return true;
- return dblcmp(p.sub(a).det(b.sub(a)))==&&dblcmp(p.sub(a).dot(p.sub(b)))<=;
- }
- //两线是否平行
- bool parallel(line v)
- {
- return dblcmp(b.sub(a).det(v.b.sub(v.a)))==;
- }
- //线段和线段关系
- //0 不相交
- //1 非规范相交
- //2 规范相交
- int segcrossseg(line v)
- {
- int d1=dblcmp(b.sub(a).det(v.a.sub(a)));
- int d2=dblcmp(b.sub(a).det(v.b.sub(a)));
- int d3=dblcmp(v.b.sub(v.a).det(a.sub(v.a)));
- int d4=dblcmp(v.b.sub(v.a).det(b.sub(v.a)));
- if ((d1^d2)==-&&(d3^d4)==-)return ;
- return (d1==&&dblcmp(v.a.sub(a).dot(v.a.sub(b)))<=||
- d2==&&dblcmp(v.b.sub(a).dot(v.b.sub(b)))<=||
- d3==&&dblcmp(a.sub(v.a).dot(a.sub(v.b)))<=||
- d4==&&dblcmp(b.sub(v.a).dot(b.sub(v.b)))<=);
- }
- //线段和直线v关系
- int linecrossseg(line v)//*this seg v line
- {
- int d1=dblcmp(b.sub(a).det(v.a.sub(a)));
- int d2=dblcmp(b.sub(a).det(v.b.sub(a)));
- if ((d1^d2)==-)return ;
- return (d1==||d2==);
- }
- //直线和直线关系
- //0 平行
- //1 重合
- //2 相交
- int linecrossline(line v)
- {
- if ((*this).parallel(v))
- {
- return v.relation(a)==;
- }
- return ;
- }
- //求两线交点
- 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));
- }
- //点p到直线的距离
- double dispointtoline(point p)
- {
- return fabs(p.sub(a).det(b.sub(a)))/length();
- }
- //点p到线段的距离
- double dispointtoseg(point p)
- {
- if (dblcmp(p.sub(b).dot(a.sub(b)))<||dblcmp(p.sub(a).dot(b.sub(a)))<)
- {
- return min(p.distance(a),p.distance(b));
- }
- return dispointtoline(p);
- }
- //XXXXXXXX
- point lineprog(point p)
- {
- return a.add(b.sub(a).mul(b.sub(a).dot(p.sub(a))/b.sub(a).len2()));
- }
- //点p关于直线的对称点
- point symmetrypoint(point p)
- {
- point q=lineprog(p);
- return point(*q.x-p.x,*q.y-p.y);
- }
- };
- struct point P[];
- struct line L[];
- int n;
- int CASE=;
- int main()
- {
- //freopen("in.txt","r",stdin);
- while (cin>>n)
- {
- if (n==) break;
- {
- CASE++;
- n--;
- for (int i=;i<=n+;i++)
- {
- scanf("%lf%lf",&P[i].x,&P[i].y);
- if (i>=)
- L[i-]=line(point(P[i-].x,P[i-].y),point(P[i].x,P[i].y));
- }
- //L[1..n]:line P[1..n]:point P[1]==P[n+1]
- vector<point> POINT;
- POINT.clear();
- int pcount=; //the number of points
- for (int i=;i<n;i++)
- for (int j=i+;j<=n;j++)
- {
- if (L[i].segcrossseg(L[j])!=)
- {
- point tm=L[i].crosspoint(L[j]);
- //printf("P: %.3f %.3f\n",tm.x,tm.y);
- bool Find=false;
- for (vector<point>::iterator it=POINT.begin();it!=POINT.end();it++)
- {
- point tp=*it;
- if ((dcmp(tp.x-tm.x))&&(dcmp(tp.y-tm.y)))
- Find=true;
- }
- if (!Find)
- {
- pcount++;
- POINT.push_back(tm);
- }
- }
- }
- for (vector<point>::iterator it=POINT.begin();it!=POINT.end();it++)
- {
- point tp=*it;
- //printf("%.5f %.5f\n",tp.x,tp.y);
- }
- int lcount=;
- for (int i=;i<=n;i++)
- {
- line tm=L[i];
- int tmp=;
- for (vector<point>::iterator it=POINT.begin();it!=POINT.end();it++)
- {
- point tp=*it;
- if (tm.pointonseg(tp))
- tmp++;
- }
- lcount=lcount+(tmp-);
- }
- //cout<<pcount<<" "<<lcount<<endl;
- //cout<<2+lcount-pcount<<endl;
- //Case 1: There are 2 pieces.
- int ans=+lcount-pcount;
- //if (ans<0) ans=2;
- printf("Case %d: There are %d pieces.\n",CASE,ans);
- }
- }
- return ;
- }
PS:在poj discussion里面有人给出了这样一组数据:
4
0 0 0 1 0 2 0 0
答案为2
这组数据我过不去 ╮(╯▽╰)╭
不过这种情况本身就够坑的,所以也不影响AC啦 ╮(╯▽╰)╭
poj2284 欧拉公式的更多相关文章
- poj2284 That Nice Euler Circuit(欧拉公式)
题目链接:poj2284 That Nice Euler Circuit 欧拉公式:如果G是一个阶为n,边数为m且含有r个区域的连通平面图,则有恒等式:n-m+r=2. 欧拉公式的推广: 对于具有k( ...
- POJ2284 That Nice Euler Circuit (欧拉公式)(计算几何 线段相交问题)
That Nice Euler Circuit Time Limit: 3000MS M ...
- hdu5047 找规律+欧拉公式
题意:在一个正方形内画n个M,求最多能分成多少个平面 sol:这种求划分成多少个平面的题第一反应肯定是欧拉公式: 二维平面上的欧拉公式:V+F-E=1 (V:Vertices,F:Faces,E:Ed ...
- UVa 10213 (欧拉公式+Java大数) How Many Pieces of Land ?
题意: 一块圆形土地,在圆周上选n个点,然后两两连线,问把这块土地分成多少块? 分析: 首先紫书上的公式是错的,不过根据书上提供的思路很容易稍加修改得到正确答案! 然后推公式吧,这里用到平面图的欧拉公 ...
- 几何学中的欧拉公式:V-E+F = 2
几何学中的欧拉公式:V-E+F = 2,V.E.F表示简单几何体的顶点数.边数.面数. 证明: 它的证明有多种,这里呈现一种递归证法. 对于任意简单几何体(几何体的边界不是曲线),我们考察这个几何体的 ...
- HDOJ 1418 抱歉(欧拉公式)
Problem Description 非常抱歉,本来兴冲冲地搞一场练习赛,由于我准备不足,出现很多数据的错误,现在这里换一个简单的题目: 前几天在网上查找ACM资料的时候,看到一个中学的奥数题目,就 ...
- D. PolandBall and Polygon BIT + 欧拉公式
http://codeforces.com/contest/755/problem/D // 我也觉得非平面图不能用欧拉公式,但是也能过,不知道为什么.求大佬留言. 这题其实就是平面图,因为它有很多个 ...
- 1418 抱歉 ACM 欧拉公式
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1418 思路:一看题目,明显是要求我们找规律,于是我就在草稿纸上画了很多个图像,还是没有找到规律,于是我就在 ...
- 2017乌鲁木齐区域赛D题Fence Building-平面图的欧拉公式
这个题B站上面有这题很完整的分析和证明,你实在不懂,可以看看这个视频 https://www.bilibili.com/video/av19849697?share_medium=android&a ...
随机推荐
- opencv 中对一个像素的rgb值或像素值进行操作的几个常用小办法【转】
You can access the Image pixels in many ways:1. One using the Inbuilt macro2. One using the pointer ...
- BI的相关问题[转]
什么是BI? Business Intelligence(BI) = Data Warehouse(DW) + OLAP + Data Mining(DM) 商业智能=数据仓库+联机分析+数据挖掘 做 ...
- C 语言学习的第 01 课:先来聊聊计算机吧
各位同学,新学期,我就是你们的助教了.我的个人信息,你们的任课老师都已经介绍过了,所以我这里也就不再啰嗦.下面,来聊聊今天的话题:“先来谈谈计算机吧”. 想必看到这个题目,你们大家一定是不愿意点击进来 ...
- 使textarea支持tab缩进
//textarea支持tab缩进 $("textarea").on( 'keydown', function(e) { if (e.keyCode == 9) { e.preve ...
- [转]Windows系统注册表知识完全揭密
来源:http://www.jb51.net/article/3328.htm Windows注册表是帮助Windows控制硬件.软件.用户环境和Windows界面的一套数据文件,注册表包含在Wind ...
- XML中的DOCTYPE属性
一.先来两个小例子 内部dtd将standalone设为真. <?xml version="1.0" standalone="yes"?> < ...
- linux基础-第十四单元 Linux网络原理及基础设置
第十四单元 Linux网络原理及基础设置 三种网卡模式图 使用ifconfig命令来维护网络 ifconfig命令的功能 ifconfig命令的用法举例 使用ifup和ifdown命令启动和停止网卡 ...
- 【Alpha版本】冲刺阶段——Day 8
我说的都队 031402304 陈燊 031402342 许玲玲 031402337 胡心颖 03140241 王婷婷 031402203 陈齐民 031402209 黄伟炜 031402233 郑扬 ...
- Eclipse导入 appcompat,design兼容包
从Android studio推出1.0正式版后,就一直在as上开发项目,但是最近要测试一个项目,是eclipse结构,导入as后,是各种报错信息,决定改成eclipse. 其中项目中用到了ppcom ...
- ueditor1.3.6jsp版在struts2应用中上传图片报"未找到上传文件"解决方案
摘要: ueditor1.3.6jsp版在struts2应用中上传图片报"未找到上传文件"解决方案 在struts2应用中使用ueditor富文本编辑器上传图片或者附件时,即使配置 ...