标签:
LA3263:
题目大意:给出一个一笔画图形,它包含n个点。先给出其n个点坐标之后,求解这个图形把平面分成了几个区域。
分析:这里要求的是面的个数,显然连直接暴力进行求解的方法都没有,因此这里就需要进行一定的转化,已知信息是点的坐标,那么我们应该能够想到平面几何中的欧拉定理(我们将图形看成图论当中的图G),经过这一步转换,我们需要做的就是求解图形的点数和边数。
点:显然这里我们就需要设置暴力,以确保能够完成所有相交情况的筛查。穷举之后,原来的节点数加交点数(去重后)就是该图中的总结点数v.
边:结合欧拉定理的适用条件,这里需要注意的是“边”的两个节点的直接连线。
简单的参考代码如下(时间原因未调试):
#include<cstdio> #include<cmath> #include<algorithm> using namespace std; const double eps = 1e-10; struct Point { double x , y; Point(double x = 0 , double y = 0):x(x),y(y){};//定义点的时候直接利用构造函数,很方便 }; 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);} int dcmp(double x) { if(fabs(x) < eps) return 0; else return x < 0 ? -1 :1; } double Cross(Vector A , Vector B)//向量叉积 { return A.x * B.y - A.y * B.x; } const int maxn = 310; Point P[maxn] , V[maxn*maxn]; bool SegmentProperIntersection(Point a1 , Point a2 , Point b1 , Point b2) { double c1 = Cross(a2 - a1 , b1 - a1); double c2 = Cross(a2 - a1 , b2 - a1); double c3 = Cross(b2 - b1 , a1 - b1); double c4 = Cross(b2 - b1 , a2 - b1); return dcmp(c1) * dcmp(c2) < 0 && dcmp(c3)*dcmp(c4) < 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; } double Dot(Vector A , Vector B){return A.x*B.x + A.y*B.y;} bool OnSegment(Point p , Point a1 , Point a2) { return dcmp(Cross(a1 - p,a2 - p)) == 0 && dcmp(Dot(a1 - p , a2 - p)) < 0; } int main() { 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 piece s.\n",++kase , e+ 2 - c); } return 0; }
标签:
原文地址:http://www.cnblogs.com/rhythmic/p/5731355.html