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 ...
随机推荐
- VS2013 抛出 stackoverflow exception 的追踪
本公司使用VWG.Caslte ActiveRecord.CSLA.net .Quantz.net 等组件做为公司的开发基础,自2007年以来,一直工作正常,但最近(2015.12月)以来,打开MDA ...
- js禁止用户右键等操作
<script type="text/javascript"> document.oncontextmenu=function(){return false}; ...
- CentOs中mysql的安装与配置
在linux中安装数据库首选MySQL,Mysql数据库的第一个版本就是发行在Linux系统上,其他选择还可以有postgreSQL,oracle等 在Linux上安装mysql数据库,我们可以去其官 ...
- QTableView 添加进度条
记录一下QTableView添加进度条 例子很小,仅供学习 使用QItemDelegate做的实现 有自动更新进度 要在.pro文件里添加 CONFIG += c++ ProgressBarDeleg ...
- 基于DDD的.NET开发框架 - ABP日志Logger集成
返回ABP系列 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应 ...
- 记、基于react-router的单页应用
现在用react写单页应用基本上都是用react-router做前端路由了吧!最近在使用react-router的过程中遇到了不少问题,在这里总结一下. 浏览器url react-router默认提供 ...
- js 0.1+0.2!=0.3
准确的说就是js小数采用ieee的64位的双精度,1位表示正负,11位指数,52位小数,所以对于0.1js是无法精确表示的的,所以会多点, http://www.jb51.net/article/77 ...
- BGP路由协议详解(完整篇)
原文链接:http://xuanbo.blog.51cto.com/499334/465596/ 2010-12-27 12:02:45 上个月我写一篇关于BGP协议的博文,曾许诺过要完善这个文档,但 ...
- AJAX——核心XMLHttpRequest对象
AJAX大家已经都知道了,是为了实现异步通讯,提高用户体验度,而将很多旧知识(XML,DOM,JavaScript,HTML,Jquery,Css……)重新融合的一个新的知识框架.而,XMLHttpR ...
- jq 修改input 标签的值
<input type="number" id="output" placeholder="0" /> jq使用方法 $('#o ...