• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
ACM s1124yy
守りたいものが 強くさせること
博客园    首页    新随笔    联系   管理     

UVALi 3263 That Nice Euler Circuit(几何)

That Nice Euler Circuit

【题目链接】That Nice Euler Circuit

【题目类型】几何

&题解:

蓝书P260 要用欧拉定理:V+F=E+2 V是顶点数;F是分成了多少区域,也就是本题的答案;E是有多少条边,比如2条线段相交,就有4条边,而不是2条.
还有几点注意:
1.dcmp()没有返回0 调了半天(模板照着敲都能错 0.0!)
2.V[]点没有去重 wa了1次(这个去重还是很难想的,去重之后还要证出原来的方法是正确的)
还有他这种算E(边数)的想法很好:就是枚举最开始给的那n条边,在每条边上找有几个点,假设有1个点在这条边上,这1条边就变成了2条边,以此类推.所以前面就要把已知的点和产生的交点找到,最后别忘了去重.

&代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

//蓝书P255
//1.点的定义
struct Point {
	double x,y;
	Point (double x=0,double y=0):x(x),y(y) {}
};
//点和向量是一样的内容 所以会出来2个名字
typedef Point Vector;
//向量+向量=向量, 点+向量=点
Vector operator + (Vector A,Vector B) {return Vector(A.x+B.x,A.y+B.y);}
//点-点=向量
Vector operator - (Point A,Point B) {return Vector(A.x-B.x,A.y-B.y);}
//向量*数=向量
Vector operator * (Vector A,double p) {return Vector(A.x*p,A.y*p);}
//向量/数=向量
Vector operator / (Vector A,double p) {return Vector(A.x/p,A.y/p);}
bool operator < (const Point& a,const Point& b) {return a.x<b.x||(a.x==b.x&&a.y<b.y);}

const double eps=1e-10;
//doublue的三态函数
int dcmp(double x) {
	if(fabs(x)<eps) return 0;
	else return x<0?-1:1;
}
bool operator == (const Point& a,const Point& b) {return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;}

//点积
double Dot(Vector A,Vector B) {return A.x*B.x+A.y*B.y;}
//向量长度
double Length(Vector A) {return sqrt(Dot(A,A));}
//向量夹角
double Angle(Vector A,Vector B) {return acos(Dot(A,B)/Length(A)/Length(B));}

//叉积
double Cross(Vector A,Vector B) {return A.x*B.y-A.y*B.x;}
//有向面积,数值是三角形面积的2倍
double Area2(Point A,Point B,Point C) {return Cross(B-A,C-A);}

//向量旋转,doublue的都是弧度
Vector Rotate(Vector A,double rad) {
	return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
}

//求单位法向量
Vector Normal(Vector A) {
	double L=Length(A);
	return Vector(-A.y/L,A.x/L);
}

//2.点和直线
//调用前请确保两条直线P+tv和Q+tw有唯一交点.当且仅当Cross(v,w)非0
Point GetLineIntersection(Point P,Vector v,Point Q,Vector w) {
	Vector u=P-Q;
	double t=Cross(w,u)/Cross(v,w);
	return P+v*t;
}

//点P到直线(过点A,B)的距离
double DistanceToLine(Point P,Point A,Point B) {
	Vector v1=B-A,v2=P-A;
	return fabs(Cross(v1,v2))/Length(v1);//不加fabs,得到的是有向距离
}

//点P到线段AB的距离
double DistanceToSegment(Point P,Point A,Point B) {
	if(A==B) return Length(P-A);
	Vector v1=B-A,v2=P-A,v3=P-B;
	if(dcmp(Dot(v1,v2))>0) return Length(v2);
	else if(dcmp(Dot(v1,v3))>0) return Length(v3);
	else return fabs(Cross(v1,v2))/Length(v1);
}

//求点P在直线AB的投影点Q
Point GetLineProjection(Point P,Point A,Point B) {
	Vector v=B-A;
	return A+v*(Dot(v,P-A)/Dot(v,v));
}

//线段相交判定,两线段恰好有一个公共点,且不在任何一条线段的端点
bool SegmentProperIntersection(Point a1,Point a2,Point b1,Point b2) {
	double c1=Cross(a2-a1,b1-a1), c2=Cross(a2-a1,b2-a1),
	       c3=Cross(b2-b1,a1-b1), c4=Cross(b2-b1,a2-b1);
	return dcmp(c1)*dcmp(c2)<0&&dcmp(c3)*dcmp(c4)<0;
}

//判断点p是否在线段a1a2上(不包含线段的端点)
bool OnSegment(Point p,Point a1,Point a2) {
	return dcmp(Cross(a1-p,a2-p))==0&&dcmp(Dot(a1-p,a2-p))<0;
	// return dcmp(Dot(a1-p,a2-p))<0;
}

//多边形的有向面积
double PolygonArea(Point* p,int n) {
	double area=0;
	for(int i=1; i<n-1; i++) {
		area+=Cross(p[i]-p[0],p[i+1]-p[0]);
	}
	return area/2;
}

//解题代码
const int maxn= 300 +7;
Point P[maxn],V[maxn*maxn];

//dcmp()没有返回0 调了半天
//V[]点没有去重 wa了1次
int main() {
	freopen("E:1.in","r",stdin);
	int n,kase=0;
	while(scanf("%d",&n)==1&&n) {
		for(int i=0; i<n; i++) {
			scanf("%lf%lf",&P[i].x,&P[i].y);
			V[i]=P[i];
		}
		n--;
		int c=n,e=n;
		for(int i=0; i<n; i++) {
			for(int j=i+1; j<n; j++) {
				if(SegmentProperIntersection(P[i],P[i+1],P[j],P[j+1])) {
					V[c++]=GetLineIntersection(P[i],P[i+1]-P[i],P[j],P[j+1]-P[j]);
				}
			}
		}
		sort(V,V+c);
		c=unique(V,V+c)-V;
		for(int i=0; i<c; i++) {
			for(int j=0; j<n; j++) {
				if(OnSegment(V[i],P[j],P[j+1])) {
					e++;
				}
			}
		}
		printf("Case %d: There are %d pieces.\n",++kase,e+2-c);
	}
	return 0;
}
posted @ 2017-04-20 00:18  s1124yy  阅读(194)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3