码迷,mamicode.com
首页 > 其他好文 > 详细

《训练指南》——8.3

时间:2016-08-03 06:42:29      阅读:118      评论:0      收藏:0      [点我收藏+]

标签:

  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;
}

 

《训练指南》——8.3

标签:

原文地址:http://www.cnblogs.com/rhythmic/p/5731355.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!