UVa 10256 - The Great Divide 判断凸包相交

模板敲错了于是WA了好几遍……

判断由红点和蓝点分别组成的两个凸包是否相离,是输出Yes,否输出No。

训练指南上的分析:

1.任取红凸包上的一条线段和蓝凸包上的一条线段,判断二者是否相交。如果相交(不一定是规范相交,有公共点就算相交),则无解

2.任取一个红点,判断是否在蓝凸包内。如果是,则无解。蓝点红凸包同理。

其中任何一个凸包退化成点或者线段时需要特判。

其实只需要把上面两个判断顺序颠倒一下,就可以不需要特判。

先判断点是否在凸包内,因为这个考虑了点在凸包边界上的情况,所以后面判凸包线段是否相交时直接用规范相交判断即可。

此时特殊情况包含在了上两种情况中,因此不需要特判。

 

  1 #include <cstdio>
  2 #include <cmath>
  3 #include <algorithm>
  4 
  5 using namespace std;
  6 
  7 const int MAXN = 540;
  8 
  9 const double eps = 1e-10;
 10 
 11 struct Point
 12 {
 13     double x, y;
 14     Point( double x = 0, double y = 0 ):x(x), y(y) { }
 15 };
 16 
 17 typedef Point Vector;
 18 
 19 Vector operator+( Vector A, Vector B )       //向量加
 20 {
 21     return Vector( A.x + B.x, A.y + B.y );
 22 }
 23 
 24 Vector operator-( Vector A, Vector B )       //向量减
 25 {
 26     return Vector( A.x - B.x, A.y - B.y );
 27 }
 28 
 29 Vector operator*( Vector A, double p )      //向量数乘
 30 {
 31     return Vector( A.x * p, A.y * p );
 32 }
 33 
 34 Vector operator/( Vector A, double p )      //向量数除
 35 {
 36     return Vector( A.x / p, A.y / p );
 37 }
 38 
 39 bool operator<( const Point& A, const Point& B )   //两点比较
 40 {
 41     return A.x < B.x || ( A.x == B.x && A.y < B.y );
 42 }
 43 
 44 int dcmp( double x )    //控制精度
 45 {
 46     if ( fabs(x) < eps ) return 0;
 47     else return x < 0 ? -1 : 1;
 48 }
 49 
 50 bool operator==( const Point& a, const Point& b )   //两点相等
 51 {
 52     return dcmp( a.x - b.x ) == 0 && dcmp( a.y - b.y ) == 0;
 53 }
 54 
 55 double Dot( Vector A, Vector B )    //向量点乘
 56 {
 57     return A.x * B.x + A.y * B.y;
 58 }
 59 
 60 double Length( Vector A )           //向量模
 61 {
 62     return sqrt( Dot( A, A ) );
 63 }
 64 
 65 double Angle( Vector A, Vector B )    //向量夹角
 66 {
 67     return acos( Dot(A, B) / Length(A) / Length(B) );
 68 }
 69 
 70 double Cross( Vector A, Vector B )   //向量叉积
 71 {
 72     return A.x * B.y - A.y * B.x;
 73 }
 74 
 75 double Area2( Point A, Point B, Point C )    //向量有向面积
 76 {
 77     return Cross( B - A, C - A );
 78 }
 79 
 80 Vector Rotate( Vector A, double rad )    //向量旋转
 81 {
 82     return Vector( A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad) );
 83 }
 84 
 85 Vector Normal( Vector A )    //向量单位法向量
 86 {
 87     double L = Length(A);
 88     return Vector( -A.y / L, A.x / L );
 89 }
 90 
 91 Point GetLineIntersection( Point P, Vector v, Point Q, Vector w )   //两直线交点
 92 {
 93     Vector u = P - Q;
 94     double t = Cross( w, u ) / Cross( v, w );
 95     return P + v * t;
 96 }
 97 
 98 double DistanceToLine( Point P, Point A, Point B )    //点到直线的距离
 99 {
100     Vector v1 = B - A, v2 = P - A;
101     return fabs( Cross( v1, v2 ) ) / Length(v1);
102 }
103 
104 double DistanceToSegment( Point P, Point A, Point B )   //点到线段的距离
105 {
106     if ( A == B ) return Length( P - A );
107     Vector v1 = B - A, v2 = P - A, v3 = P - B;
108     if ( dcmp( Dot(v1, v2) ) < 0 ) return Length(v2);
109     else if ( dcmp( Dot(v1, v3) ) > 0 ) return Length(v3);
110     else return fabs( Cross( v1, v2 ) ) / Length(v1);
111 }
112 
113 Point GetLineProjection( Point P, Point A, Point B )    // 点在直线上的投影
114 {
115     Vector v = B - A;
116     return A + v*( Dot(v, P - A) / Dot( v, v ) );
117 }
118 
119 bool SegmentProperIntersection( Point a1, Point a2, Point b1, Point b2 )  //线段相交,交点不在端点
120 {
121     double c1 = Cross( a2 - a1, b1 - a1 ), c2 = Cross( a2 - a1, b2 - a1 ),
122                 c3 = Cross( b2 - b1, a1 - b1 ), c4 = Cross( b2 - b1, a2 - b1 );
123     return dcmp(c1)*dcmp(c2) < 0 && dcmp(c3) * dcmp(c4) < 0;
124 }
125 
126 bool OnSegment( Point p, Point a1, Point a2 )   //点在线段上,不包含端点
127 {
128     return dcmp( Cross(a1 - p, a2 - p) ) == 0 && dcmp( Dot( a1 - p, a2 - p ) ) < 0;
129 }
130 
131 double toRad( double deg )   //角度转弧度
132 {
133     return deg / 180.0 * acos( -1.0 );
134 }
135 
136 int ConvexHull( Point *p, int n, Point *ch )    //求凸包
137 {
138     sort( p, p + n );
139     n = unique( p, p + n ) - p;
140     int m = 0;
141     for ( int i = 0; i < n; ++i )
142     {
143         while ( m > 1 && Cross( ch[m - 1] - ch[m - 2], p[i] - ch[m - 2] ) <= 0 ) --m;
144         ch[m++] = p[i];
145     }
146 
147     int k = m;
148     for ( int i = n - 2; i >= 0; --i )
149     {
150         while ( m > k && Cross( ch[m - 1] - ch[m - 2], p[i] - ch[m - 2] ) <= 0 ) --m;
151         ch[m++] = p[i];
152     }
153 
154     if ( n > 1 ) --m;
155     return m;
156 }
157 
158 int isPointInPolygon( Point p, Point *poly, int n )   //判断一点是否在凸包内
159 {
160     int wn = 0;
161 
162     for ( int i = 0; i < n; ++i )
163     {
164         Point& p1 = poly[i], p2 = poly[ (i + 1)%n ];
165         if ( p == p1 || p == p2 || OnSegment( p, p1, p2 ) ) return -1;  //在边界上
166         int k = dcmp( Cross( p2 - p1, p - p1 ) );
167         int d1 = dcmp( p1.y - p.y );
168         int d2 = dcmp( p2.y - p.y );
169         if ( k > 0 && d1 <= 0 && d2 > 0 ) ++wn;
170         if ( k < 0 && d2 <= 0 && d1 > 0 ) --wn;
171     }
172 
173     if ( wn ) return 1;   //内部
174     return 0;             //外部
175 }
176 
177 double PolygonArea( Point *p, int n )   //多边形有向面积
178 {
179     double area = 0;
180     for ( int i = 1; i < n - 1; ++i )
181         area += Cross( p[i] - p[0], p[i + 1] - p[0] );
182     return area / 2.0;
183 }
184 
185 bool checkConvexHullIntersection( Point *a, Point *b, int na, int nb )
186 {
187     for ( int i = 0; i < na; ++i )
188         if ( isPointInPolygon( a[i], b, nb ) ) return true;
189 
190     for ( int i = 0; i < nb; ++i )
191         if ( isPointInPolygon( b[i], a, na ) ) return true;
192 
193     for ( int i = 0; i < na; ++i )
194         for ( int j = 0; j < nb; ++j )
195             if ( SegmentProperIntersection(a[i], a[ (i + 1) % na ], b[j], b[ (j + 1) % nb ] ) ) return true;
196 
197     return false;
198 }
199 
200 Point M[MAXN], chM[MAXN];
201 Point C[MAXN], chC[MAXN];
202 
203 int main()
204 {
205     int Mn, Cn;
206     while ( scanf( "%d%d", &Mn, &Cn ), Mn || Cn )
207     {
208         for ( int i = 0; i < Mn; ++i )
209             scanf( "%lf%lf", &M[i].x, &M[i].y );
210 
211         for ( int i = 0; i < Cn; ++i )
212             scanf( "%lf%lf", &C[i].x, &C[i].y );
213 
214         int Mcnt = ConvexHull( M, Mn, chM );
215         int Ccnt = ConvexHull( C, Cn, chC );
216 
217         if ( checkConvexHullIntersection( chM, chC, Mcnt, Ccnt ) ) puts("No");
218         else puts("Yes");
219     }
220     return 0;
221 }

 

 

转载于:https://www.cnblogs.com/GBRgbr/p/3142838.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
The Cortex-M0 processor does not have a hardware divider, which means that division calculations are performed using software routines. There are various algorithms for performing software division, but one commonly used method is called "long division". In long division, the divisor is repeatedly subtracted from the dividend until the remainder is less than the divisor. The number of times the divisor is subtracted is the quotient, and the remainder is the final result. This process is repeated until all digits of the dividend have been processed. Here is a sample code for performing integer division on Cortex-M0 using long division: ``` int divide(int dividend, int divisor) { int quotient = 0, remainder = 0; int sign = ((dividend < 0) ^ (divisor < 0)) ? -1 : 1; // convert both operands to positive if (dividend < 0) dividend = -dividend; if (divisor < 0) divisor = -divisor; // perform long division for (int i = 31; i >= 0; i--) { remainder <<= 1; // left shift remainder remainder |= (dividend >> i) & 1; // add next bit from dividend to remainder if (remainder >= divisor) { remainder -= divisor; quotient |= (1 << i); // set corresponding bit in quotient } } // apply sign quotient = sign * quotient; return quotient; } ``` Note that this code assumes that both the dividend and divisor are 32-bit integers. It also handles negative operands correctly and applies the correct sign to the result. However, it may not be the most efficient implementation and may need to be optimized for specific use cases.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值