应用平面图的欧拉定理:V + F - E = 2
两两线段求交,得到交点数 V,然后判断每个交点落在几条边上,如果一个点在一条边上,这条边就分裂成两条边,边数加 1。这样得到边数 E。最后直接用欧拉定理解得 F。


/*************************************************************************
Author: WHU_GCC
Created Time: 2007-8-20 12:52:55
File Name: pku2284.cpp
Description: 
***********************************************************************
*/

#include 
<iostream>
#include 
<cmath>
using namespace std;
#define out(x) (cout<<#x<<": "<<x<<endl)
const int maxint=0x7FFFFFFF;
typedef 
long long int64;
const int64 maxint64 = 0x7FFFFFFFFFFFFFFFLL;
template
<class T>void show(T a, int n){for(int i=0; i<n; ++i) cout<<a[i]<<' '; cout<<endl;}
template
<class T>void show(T a, int r, int l){for(int i=0; i<r; ++i)show(a[i],l);cout<<endl;}

const double INF = 1e200;
const double EP = 1e-10;

struct point_t
{
    
double x, y;
    point_t(
double a = 0double b = 0)
    
{
        x 
= a;
        y 
= b;
    }

}
;

struct lineseg_t
{
    point_t s, e;
    lineseg_t (point_t a, point_t b)
    
{
        s 
= a;
        e 
= b;
    }

    lineseg_t()
    
{}
}
;

struct line_t
{
    
double a, b, c;
}
;

bool operator <(point_t p1, point_t p2)
{
    
return p1.x < p2.x || p1.x == p2.x && p1.y < p2.y;
}



bool operator ==(point_t p1, point_t p2)
{
    
return abs(p1.x - p2.x) < EP && abs(p1.y - p2.y) < EP;
}


double multiply(point_t sp, point_t ep, point_t op)
{
    
return (sp.x - op.x) * (ep.y - op.y) - (ep.x - op.x) * (sp.y - op.y);
}


bool online(lineseg_t l, point_t p)
{
    
return abs(multiply(l.e, p, l.s)) < EP && (p.x - l.s.x) * (p.x - l.e.x) < EP && (p.y - l.s.y) * (p.y - l.e.y) < EP;
}


bool lineintersect(line_t l1, line_t l2, point_t &p)
{
    
double d = l1.a * l2.b - l2.a * l1.b;
    
if (abs(d) < EP) return false;
    p.x 
= (l2.c * l1.b - l1.c * l2.b) / d;
    p.y 
= (l2.a * l1.c - l1.a * l2.c) / d;
    
return true;
}


line_t makeline(point_t p1, point_t p2)
{
    line_t t1;
    
int sign = 1;
    t1.a 
= p2.y - p1.y;
    
if (t1.a < 0)
    
{
        sign 
= -1;
        t1.a 
= sign * t1.a;
    }

    t1.b 
= sign * (p1.x - p2.x);
    t1.c 
= sign * (p1.y * p2.x - p1.x * p2.y);
    
return t1;
}


bool intersection(lineseg_t l1, lineseg_t l2, point_t &p)
{
    line_t ll1, ll2;
    ll1 
= makeline(l1.s, l1.e);
    ll2 
= makeline(l2.s, l2.e);
    
if (lineintersect(ll1, ll2, p))
        
return online(l1, p) && online(l2, p);
    
else return false;
}


const int maxn = 100000;
point_t p[maxn];
int n;

point_t inter[maxn];
int cnt_inter;

int main()
{
    
int ca = 1;
    
while (scanf("%d"&n), n != 0)
    
{
        
for (int i = 0; i < n; i++)
            scanf(
"%lf%lf"&p[i].x, &p[i].y);
        
        cnt_inter 
= 0;
        
for (int i = 0; i < n; i++)
            
for (int j = 0; j < n; j++)
            
{
                lineseg_t l1(p[i], p[(i 
+ 1% n]), l2(p[j], p[(j + 1% n]);
                point_t p;
                
if (intersection(l1, l2, p))
                    inter[cnt_inter
++= p;
            }

        sort(inter, inter 
+ cnt_inter);
        cnt_inter 
= unique(inter, inter + cnt_inter) - inter;
        
        
int e = 0;
        
for (int i = 0; i < cnt_inter; i++)
        
{
            
for (int j = 0; j < n; j++)
            
{
                lineseg_t t(p[j], p[(j 
+ 1% n]);
                
if (online(t, inter[i]) && !(t.s == inter[i]))
                    e
++;
            }

        }

        printf(
"Case %d: There are %d pieces.\n", ca++, e + 2 - cnt_inter);
    }

    
return 0;
}
posted on 2007-08-21 17:26 Felicia 阅读(345) 评论(0)  编辑 收藏 引用 所属分类: 计算几何

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理