zoukankan      html  css  js  c++  java
  • 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:

      1 #include<vector>
      2 #include<list>
      3 #include<map>
      4 #include<set>
      5 #include<deque>
      6 #include<queue>
      7 #include<stack>
      8 #include<bitset>
      9 #include<algorithm>
     10 #include<functional>
     11 #include<numeric>
     12 #include<utility>
     13 #include<iostream>
     14 #include<sstream>
     15 #include<iomanip>
     16 #include<cstdio>
     17 #include<cmath>
     18 #include<cstdlib>
     19 #include<cctype>
     20 #include<string>
     21 #include<cstring>
     22 #include<cstdio>
     23 #include<cmath>
     24 #include<cstdlib>
     25 #include<ctime>
     26 #include<climits>
     27 #include<complex>
     28 #define mp make_pair
     29 #define pb push_back
     30 using namespace std;
     31 const double eps=1e-8;//精度
     32 const double pi=acos(-1.0);//π
     33 const double inf=1e20;//无穷大
     34 const int maxp=1111;//最大点数
     35 /*
     36     判断d是否在精度内等于0
     37 */
     38 int dblcmp(double d)
     39 {
     40     if (fabs(d)<eps)return 0;
     41     return d>eps?1:-1;
     42 }
     43 
     44 
     45 bool dcmp(double x)
     46 {
     47     return (fabs(x)<eps);
     48 }
     49 
     50 /*
     51     求x的平方
     52 */
     53 inline double sqr(double x){return x*x;}
     54 /*
     55     点/向量
     56 */
     57 struct point
     58 {
     59     double x,y;
     60     point(){}
     61     point(double _x,double _y):x(_x),y(_y){};
     62     //读入一个点
     63     void input()
     64     {
     65         scanf("%lf%lf",&x,&y);
     66     }
     67     //输出一个点
     68     void output()
     69     {
     70         printf("%.2f %.2f
    ",x,y);
     71     }
     72     //判断两点是否相等
     73     bool operator==(point a)const
     74     {
     75         return dblcmp(a.x-x)==0&&dblcmp(a.y-y)==0;
     76     }
     77     //判断两点大小
     78     bool operator<(point a)const
     79     {
     80         return dblcmp(a.x-x)==0?dblcmp(y-a.y)<0:x<a.x;
     81     }
     82     //点到源点的距离/向量的长度
     83     double len()
     84     {
     85         return hypot(x,y);
     86     }
     87     //点到源点距离的平方
     88     double len2()
     89     {
     90         return x*x+y*y;
     91     }
     92     //两点间的距离
     93     double distance(point p)
     94     {
     95         return hypot(x-p.x,y-p.y);
     96     }
     97     //向量加
     98     point add(point p)
     99     {
    100         return point(x+p.x,y+p.y);
    101     }
    102     //向量减
    103     point sub(point p)
    104     {
    105         return point(x-p.x,y-p.y);
    106     }
    107     //向量乘
    108     point mul(double b)
    109     {
    110         return point(x*b,y*b);
    111     }
    112     //向量除
    113     point div(double b)
    114     {
    115         return point(x/b,y/b);
    116     }
    117     //点乘
    118     double dot(point p)
    119     {
    120         return x*p.x+y*p.y;
    121     }
    122     //叉乘
    123     double det(point p)
    124     {
    125         return x*p.y-y*p.x;
    126     }
    127     //XXXXXXX
    128     double rad(point a,point b)
    129     {
    130         point p=*this;
    131         return fabs(atan2(fabs(a.sub(p).det(b.sub(p))),a.sub(p).dot(b.sub(p))));
    132     }
    133     //截取长度r
    134     point trunc(double r)
    135     {
    136         double l=len();
    137         if (!dblcmp(l))return *this;
    138         r/=l;
    139         return point(x*r,y*r);
    140     }
    141     //左转90度
    142     point rotleft()
    143     {
    144         return point(-y,x);
    145     }
    146     //右转90度
    147     point rotright()
    148     {
    149         return point(y,-x);
    150     }
    151     //绕点p逆时针旋转angle角度
    152     point rotate(point p,double angle)
    153     {
    154         point v=this->sub(p);
    155         double c=cos(angle),s=sin(angle);
    156         return point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c);
    157     }
    158 };
    159 
    160 bool point_cmp(point a,point b)
    161 {
    162     return ((dcmp(a.x-b.x))&&(dcmp(a.y-b.y)));
    163 }
    164 
    165 /*
    166     线段/直线
    167 */
    168 struct line
    169 {
    170     point a,b;
    171     line(){}
    172     line(point _a,point _b)
    173     {
    174         a=_a;
    175         b=_b;
    176     }
    177     //判断线段相等
    178     bool operator==(line v)
    179     {
    180         return (a==v.a)&&(b==v.b);
    181     }
    182     //点p做倾斜角为angle的射线
    183     line(point p,double angle)
    184     {
    185         a=p;
    186         if (dblcmp(angle-pi/2)==0)
    187         {
    188             b=a.add(point(0,1));
    189         }
    190         else
    191         {
    192             b=a.add(point(1,tan(angle)));
    193         }
    194     }
    195     //直线一般式ax+by+c=0
    196     line(double _a,double _b,double _c)
    197     {
    198         if (dblcmp(_a)==0)
    199         {
    200             a=point(0,-_c/_b);
    201             b=point(1,-_c/_b);
    202         }
    203         else if (dblcmp(_b)==0)
    204         {
    205             a=point(-_c/_a,0);
    206             b=point(-_c/_a,1);
    207         }
    208         else
    209         {
    210             a=point(0,-_c/_b);
    211             b=point(1,(-_c-_a)/_b);
    212         }
    213     }
    214     //读入一个线段
    215     void input()
    216     {
    217         a.input();
    218         b.input();
    219     }
    220     //校准线段两点
    221     void adjust()
    222     {
    223         if (b<a)swap(a,b);
    224     }
    225     //线段长度
    226     double length()
    227     {
    228         return a.distance(b);
    229     }
    230     //直线倾斜角 0<=angle<180
    231     double angle()
    232     {
    233         double k=atan2(b.y-a.y,b.x-a.x);
    234         if (dblcmp(k)<0)k+=pi;
    235         if (dblcmp(k-pi)==0)k-=pi;
    236         return k;
    237     }
    238     //点和线段关系
    239     //1 在逆时针
    240     //2 在顺时针
    241     //3 平行
    242     int relation(point p)
    243     {
    244         int c=dblcmp(p.sub(a).det(b.sub(a)));
    245         if (c<0)return 1;
    246         if (c>0)return 2;
    247         return 3;
    248     }
    249     //点是否在线段上
    250     bool pointonseg(point p)
    251     {
    252         //if ((p==a) || (p==b))  return true;
    253         return dblcmp(p.sub(a).det(b.sub(a)))==0&&dblcmp(p.sub(a).dot(p.sub(b)))<=0;
    254     }
    255     //两线是否平行
    256     bool parallel(line v)
    257     {
    258         return dblcmp(b.sub(a).det(v.b.sub(v.a)))==0;
    259     }
    260     //线段和线段关系
    261     //0 不相交
    262     //1 非规范相交
    263     //2 规范相交
    264     int segcrossseg(line v)
    265     {
    266         int d1=dblcmp(b.sub(a).det(v.a.sub(a)));
    267         int d2=dblcmp(b.sub(a).det(v.b.sub(a)));
    268         int d3=dblcmp(v.b.sub(v.a).det(a.sub(v.a)));
    269         int d4=dblcmp(v.b.sub(v.a).det(b.sub(v.a)));
    270         if ((d1^d2)==-2&&(d3^d4)==-2)return 2;
    271         return (d1==0&&dblcmp(v.a.sub(a).dot(v.a.sub(b)))<=0||
    272                 d2==0&&dblcmp(v.b.sub(a).dot(v.b.sub(b)))<=0||
    273                 d3==0&&dblcmp(a.sub(v.a).dot(a.sub(v.b)))<=0||
    274                 d4==0&&dblcmp(b.sub(v.a).dot(b.sub(v.b)))<=0);
    275     }
    276     //线段和直线v关系
    277     int linecrossseg(line v)//*this seg v line
    278     {
    279         int d1=dblcmp(b.sub(a).det(v.a.sub(a)));
    280         int d2=dblcmp(b.sub(a).det(v.b.sub(a)));
    281         if ((d1^d2)==-2)return 2;
    282         return (d1==0||d2==0);
    283     }
    284     //直线和直线关系
    285     //0 平行
    286     //1 重合
    287     //2 相交
    288     int linecrossline(line v)
    289     {
    290         if ((*this).parallel(v))
    291         {
    292             return v.relation(a)==3;
    293         }
    294         return 2;
    295     }
    296     //求两线交点
    297     point crosspoint(line v)
    298     {
    299         if ((point_cmp(a,v.a))||(point_cmp(a,v.b)))     return a;
    300         if ((point_cmp(b,v.a))||(point_cmp(b,v.b)))     return b;
    301         double a1=v.b.sub(v.a).det(a.sub(v.a));
    302         double a2=v.b.sub(v.a).det(b.sub(v.a));
    303         return point((a.x*a2-b.x*a1)/(a2-a1),(a.y*a2-b.y*a1)/(a2-a1));
    304     }
    305 
    306     //点p到直线的距离
    307     double dispointtoline(point p)
    308     {
    309         return fabs(p.sub(a).det(b.sub(a)))/length();
    310     }
    311     //点p到线段的距离
    312     double dispointtoseg(point p)
    313     {
    314         if (dblcmp(p.sub(b).dot(a.sub(b)))<0||dblcmp(p.sub(a).dot(b.sub(a)))<0)
    315         {
    316             return min(p.distance(a),p.distance(b));
    317         }
    318         return dispointtoline(p);
    319     }
    320     //XXXXXXXX
    321     point lineprog(point p)
    322     {
    323         return a.add(b.sub(a).mul(b.sub(a).dot(p.sub(a))/b.sub(a).len2()));
    324     }
    325     //点p关于直线的对称点
    326     point symmetrypoint(point p)
    327     {
    328         point q=lineprog(p);
    329         return point(2*q.x-p.x,2*q.y-p.y);
    330     }
    331 };
    332 
    333 
    334 struct point P[1000];
    335 struct line  L[1000];
    336 int n;
    337 int CASE=0;
    338 
    339 int main()
    340 {
    341     //freopen("in.txt","r",stdin);
    342 
    343     while (cin>>n)
    344     {
    345         if (n==0)   break;
    346         {
    347             CASE++;
    348             n--;
    349             for (int i=1;i<=n+1;i++)
    350             {
    351                 scanf("%lf%lf",&P[i].x,&P[i].y);
    352                 if (i>=2)
    353                     L[i-1]=line(point(P[i-1].x,P[i-1].y),point(P[i].x,P[i].y));
    354             }
    355             //L[1..n]:line      P[1..n]:point   P[1]==P[n+1]
    356 
    357             vector<point> POINT;
    358             POINT.clear();
    359 
    360             int pcount=0;       //the number of points
    361             for (int i=1;i<n;i++)
    362                 for (int j=i+1;j<=n;j++)
    363                 {
    364                     if (L[i].segcrossseg(L[j])!=0)
    365                     {
    366                         point tm=L[i].crosspoint(L[j]);
    367                         //printf("P:   %.3f   %.3f
    ",tm.x,tm.y);
    368                         bool Find=false;
    369                         for (vector<point>::iterator it=POINT.begin();it!=POINT.end();it++)
    370                         {
    371                             point tp=*it;
    372                             if ((dcmp(tp.x-tm.x))&&(dcmp(tp.y-tm.y)))
    373                                 Find=true;
    374                         }
    375                         if (!Find)
    376                         {
    377                             pcount++;
    378                             POINT.push_back(tm);
    379                         }
    380                     }
    381                 }
    382 
    383             for (vector<point>::iterator it=POINT.begin();it!=POINT.end();it++)
    384             {
    385                 point tp=*it;
    386                 //printf("%.5f %.5f
    ",tp.x,tp.y);
    387             }
    388 
    389             int lcount=0;
    390             for (int i=1;i<=n;i++)
    391             {
    392                 line tm=L[i];
    393                 int tmp=0;
    394                 for (vector<point>::iterator it=POINT.begin();it!=POINT.end();it++)
    395                 {
    396                     point tp=*it;
    397                     if (tm.pointonseg(tp))
    398                         tmp++;
    399                 }
    400                 lcount=lcount+(tmp-1);
    401             }
    402 
    403             //cout<<pcount<<"   "<<lcount<<endl;
    404             //cout<<2+lcount-pcount<<endl;
    405             //Case 1: There are 2 pieces.
    406             int ans=2+lcount-pcount;
    407             //if (ans<0)  ans=2;
    408             printf("Case %d: There are %d pieces.
    ",CASE,ans);
    409         }
    410     }
    411 
    412 
    413     return 0;
    414 }
    View Code

    PS:在poj discussion里面有人给出了这样一组数据:

    4

    0 0 0 1 0 2 0 0    

    答案为2

    这组数据我过不去 ╮(╯▽╰)╭

    不过这种情况本身就够坑的,所以也不影响AC啦 ╮(╯▽╰)╭

  • 相关阅读:
    影响指令流水线的因素
    硬布线控制器和微程序控制器 
    总线仲裁
    计算机专业面试
    P、NP、NPC、NPH问题的区别和联系
    多态
    软件生命周期
    你所不知道的js的小知识点(1)
    html span标签 不换行(有时span带中文时候是可以自动换行的)
    form的onsubmit事件--表单提交前的验证最佳实现方式
  • 原文地址:https://www.cnblogs.com/pdev/p/4260238.html
Copyright © 2011-2022 走看看