Im_hear

导航

zoj 1010

View Code
  1 #include <iostream>
  2 #include <cmath> 
  3 using namespace std;
  4 
  5 // 精度容差 
  6 const double EPS = 1e-5; 
  7 
  8 // 允许容差的浮点数相等 
  9 inline bool equals( double x, double y ) {
 10     return fabs( x - y ) < EPS;
 11 }
 12 
 13 // 点结构 
 14 struct Point {
 15     Point() {}
 16     Point( double x, double y ) : posX( x ), posY( y ) {}
 17     void getPoint() { cin >> posX >> posY; }
 18     double posX, posY;
 19 };
 20 
 21 // 判断两点是否重合 
 22 bool cover( Point pointA, Point pointB ) {
 23     return fabs( pointA.posX - pointB.posX ) +
 24         fabs( pointA.posY - pointB.posY ) < EPS; 
 25 }
 26 
 27 // 线段类 
 28 class LineSegment {
 29 public:
 30     LineSegment() {}
 31     // 构造函数,两点一线 
 32     LineSegment( Point pA, Point pB ) : pointA( pA ), pointB( pB ) {}
 33     // 判别点在线的哪一侧,返回值为叉积 
 34     double pointOnItsSide( Point );
 35     // 判别点是否在线上 
 36     bool pointOnLine( Point );
 37     // 判别两线是否相交 
 38     friend bool cross( LineSegment, LineSegment );
 39 private:
 40     Point pointA, pointB;
 41 };
 42 
 43 double LineSegment :: pointOnItsSide( Point point ) {
 44     return ( point.posX - pointA.posX ) * ( pointB.posY - pointA.posY ) -
 45         ( point.posY - pointA.posY ) * ( pointB.posX - pointA.posX );
 46 } 
 47 
 48 bool LineSegment :: pointOnLine( Point point ) {
 49     // 若端点重合,必定相交 
 50     if( cover( point, pointA ) || cover( point, pointB ) ) return true;
 51     // 若点在线段坐标顶点方框外,必定不相交 
 52     if( point.posX > pointA.posX && point.posX > pointB.posX ||
 53         point.posX < pointA.posX && point.posX < pointB.posX ||
 54         point.posY > pointA.posY && point.posY > pointB.posY ||
 55         point.posY < pointA.posY && point.posY < pointB.posY ) return false;
 56     // 否则,点必定不在延长线或端点上,只要点与直线叉积非零即不在线上
 57     return equals( pointOnItsSide( point ), 0.0 );
 58 }
 59 
 60 bool cross( LineSegment lineA, LineSegment lineB ) {
 61     // 若一条直线端点在另一直线上,必然相交 
 62     if( lineA.pointOnLine( lineB.pointA ) || lineA.pointOnLine( lineB.pointB ) ||
 63         lineB.pointOnLine( lineA.pointA ) || lineB.pointOnLine( lineA.pointB ) ) return true;
 64     double prod11 = lineA.pointOnItsSide( lineB.pointA ),
 65         prod12 = lineA.pointOnItsSide( lineB.pointB ),
 66         prod21 = lineB.pointOnItsSide( lineA.pointA ),
 67         prod22 = lineB.pointOnItsSide( lineA.pointB );
 68     return prod11 * prod12 < -EPS && prod21 * prod22 < -EPS;
 69 }
 70 
 71 // 多边形类
 72 class Polygon {
 73 public:
 74     Polygon() {}
 75     int getPolygon();
 76     bool isValid();
 77     double area(); 
 78 private:
 79     int size; 
 80     Point vertex[1000];
 81     LineSegment edge[1000]; 
 82 };
 83 
 84 int Polygon :: getPolygon() {
 85     cin >> size;
 86     int i = 0;
 87     for(  i = 0; i < size; i++ )
 88         vertex[i].getPoint();
 89     for(  i = 1; i < size; i++ )
 90         edge[i] = LineSegment( vertex[i - 1], vertex[i] );
 91     edge[0] = LineSegment( vertex[size - 1], vertex[0] );
 92     return size;
 93 }
 94 
 95 bool Polygon :: isValid() {
 96     if( size < 3 )
 97         return false;
 98     if( size == 3 )
 99         return !fabs( LineSegment( vertex[0], vertex[1] ).pointOnItsSide( vertex[2] ) ) < EPS;
100     for( int j = 2; j < size - 1; j++ )
101         if( cross( edge[0], edge[j] ) ) return false;
102         for( int i = 1; i < size - 2; i++ )
103             for( int j = i + 2; j < size; j++ )
104                 if( cross( edge[i], edge[j] ) )
105                     return false;
106                 return true;
107 } 
108 
109 double Polygon :: area() {
110     double ans = 0.0;
111     if( size < 3 ) return ans;
112     for( int i = 2; i < size; i++ )
113         ans += edge[i].pointOnItsSide( vertex[0] );
114     return fabs( ans / 2.0 );
115 }
116 
117 int main() 
118 {
119     Polygon Pattern;
120     int T = 1;
121     cout.setf( ios :: fixed );
122     cout.precision( 2 );
123     while( Pattern.getPolygon() ) {
124         if( T != 1 ) cout << endl;
125         cout << "Figure " << T++ << ": ";
126         if( !Pattern.isValid() )
127             cout << "Impossible" << endl;
128         else cout << Pattern.area() << endl;
129     }
130     return 0;
131 }

 

 代码一用c++的风格,代码二用c风格。

View Code 2
 1 #include<stdio.h>
 2 #define max(a,b) ((a)>(b)?(a):(b))
 3 #define min(a,b) ((a)<(b)?(a):(b))
 4 double x[1000],y[1000];
 5 
 6 //叉积,p0p1 X p0p2,>0 p0p2沿着p0右旋得到p0p1,<0 左旋得到,=0 共线
 7 double multi(int p1,int p2,int p0)
 8 {
 9  return (x[p1]-x[p0])*(y[p2]-y[p0])-(x[p2]-x[p0])*(y[p1]-y[p0]);
10 }
11 int isIntersected(int s1,int e1,int s2,int e2)//线段s1e1与s2e2是否相交
12 {
13  if(max(x[s1],x[e1])<min(x[s2],x[e2]))
14   return 0;
15  if(max(x[s2],x[e2])<min(x[s1],x[e1]))
16   return 0;
17  if(max(y[s1],y[e1])<min(y[s2],y[e2]))
18   return 0;
19  if(max(y[s2],y[e2])<min(y[s1],y[e1]))
20   return 0;
21  if(multi(s2,e1,s1)*multi(e1,e2,s1)<0)
22   return 0;
23  if(multi(s1,e2,s2)*multi(e2,e1,s2)<0)
24   return 0;
25  return 1;
26 }
27 double polygonArea(int n)//计算多边形面积,凹凸多边形皆可
28 {
29  double area=0;
30  int i;
31  for(i=1;i<n;i++)
32   area+=x[i-1]*y[i]-x[i]*y[i-1];
33  area+=x[n-1]*y[0]-x[0]*y[n-1];
34  if(area<0)   // 得到的是有向面积,取绝对值
35   area*=-1;
36  return area/2;
37 }
38 int main()
39 {
40  freopen("in.txt","r",stdin);
41  int n,caseNum=0,i,j;
42  double area=0;
43 begin: while(scanf("%d",&n)&&n)
44   {
45    caseNum++;
46    if(caseNum>1)
47     printf("\n");
48    for(i=0;i<n;i++)
49     scanf("%lf %lf",&x[i],&y[i]);
50    if(n<3)   //小于三个点不可能组成多边形
51    {
52     printf("Figure %d: Impossible\n",caseNum);
53     continue;
54    }
55    for(i=1;i<=n-1;i++)  //判断能否组成多边形
56    {
57     for(j=1;j<=i-2;j++)
58      if(isIntersected(i-1,i,j-1,j))
59      {
60       printf("Figure %d: Impossible\n",caseNum);
61       goto begin;
62      }
63    }
64    for(i=2;i<n-1;i++)
65     if(isIntersected(n-1,0,i-1,i))
66     {
67      printf("Figure %d: Impossible\n",caseNum);
68      goto begin;
69     }
70    //计算多边形面积
71    printf("Figure %d: %.2lf\n",caseNum,polygonArea(n));
72   }
73   return 0;
74 }

posted on 2012-05-13 16:02  Im_hear  阅读(235)  评论(0编辑  收藏  举报