http://acm.pku.edu.cn/JudgeOnline/problem?id=1474
#include
<
cmath
>
#include < stdio.h >
#include < string .h >
#include < algorithm >
#include < iostream >
using namespace std;
typedef double TYPE;
#define MaxPoint 110
#define Epsilon 1e-10 /*验证* // /精度的范围 ,根据不同的情况调整精度值
// 空间中的点,可以用来作为二维点来用
struct POINT { /* 验证 */
TYPE x; TYPE y; TYPE z;
POINT() : x( 0 ), y( 0 ), z( 0 ) {};
POINT(TYPE _x_, TYPE _y_, TYPE _z_ = 0 )
: x(_x_), y(_y_), z(_z_) {};
// 要用 G++ 提交 ,可以不用这个
POINT operator = ( const POINT & A){
x = A.x;
y = A.y;
z = A.z;
}
};
// 多边形 ,逆时针或顺时针给出x,y
struct POLY { /* 验证 */
// n个点
int n;
// x,y为点的指针,首尾必须重合
TYPE * x;
TYPE * y;
POLY() : n( 0 ), x(NULL), y(NULL) {};
POLY( int _n_, const TYPE * _x_, const TYPE * _y_) {
n = _n_;
x = new TYPE[n + 1 ];
memcpy(x, _x_, n * sizeof (TYPE));
x[n] = _x_[ 0 ];
y = new TYPE[n + 1 ];
memcpy(y, _y_, n * sizeof (TYPE));
y[n] = _y_[ 0 ];
}
};
// 判断 x 是正数还是负数
inline int Sign(TYPE x){ /* 验证 */
return x <- Epsilon ?- 1 :x > Epsilon;
}
void Interect(POINT x,POINT y,TYPE a,TYPE b,TYPE c, int & s,POINT q[]){
TYPE u = fabs(a * x.x + b * x.y + c);
TYPE v = fabs(a * y.x + b * y.y + c);
q[ ++ s].x = (x.x * v + y.x * u) / (u + v);
q[s].y = (x.y * v + y.y * u) / (u + v);
}
// 利用半平面切割
void Cut(TYPE a,TYPE b,TYPE c, int & KarnalPoint,POINT p[])
{
int s = 0 ;
int i;
POINT q[MaxPoint];
for (i = 1 ; i <= KarnalPoint; i ++ ){ // 遍历所有顶点是否能观察到该边
if (Sign(a * p[i].x + b * p[i].y + c) >= 0 ){ // 因为线段是顺时针给出的,如果是逆时针就是<=0
q[ ++ s] = p[i]; // 若是则存储
}
else {
if (Sign(a * p[i - 1 ].x + b * p[i - 1 ].y + c) > 0 ) // 逆时针就是<0
Interect(p[i - 1 ], p[i], a, b, c, s, q);
if (Sign(a * p[i + 1 ].x + b * p[i + 1 ].y + c) > 0 ) // 逆时针就是<0
Interect(p[i + 1 ], p[i], a, b, c, s, q);
}
}
// 最后的p数组存放半平面的点集合
for (i = 1 ;i <= s;i ++ )
p[i] = q[i];
p[s + 1 ] = p[ 1 ],p[ 0 ] = p[s];
KarnalPoint = s;
}
POLY PolygonKernal( int n, POINT point[])
{
int KarnalPoint = n;
POINT p[MaxPoint]; // p 的大小和 tr 的大小一样
for ( int i = 0 ; i < n; i ++ ){
p[i + 1 ] = point[i]; // 初始化边界
}
point[n] = point[ 0 ];
p[n + 1 ] = p[ 1 ];
p[ 0 ] = p[n];
TYPE a,b,c;
for ( int i = 0 ;i < n;i ++ ){
a = point[i + 1 ].y - point[i].y ; // 计算出相邻两点所在直线ax+by+c=0
b = point[i].x - point[i + 1 ].x;
c = point[i + 1 ].x * point[i].y - point[i].x * point[i + 1 ].y;
Cut(a, b, c, KarnalPoint, p);
}
TYPE X[MaxPoint],Y[MaxPoint];
for ( int i = 0 ; i < KarnalPoint; i ++ ){
X[i] = p[i].x;
Y[i] = p[i].y;
}
POLY poly(KarnalPoint, X, Y);
return poly;
}
int main(){
int n,t;
POINT point[MaxPoint];
int cases = 1 ;
while (cin >> n,n != 0 )
{
if (cases != 1 ) puts( "" );
for ( int i = 0 ;i < n;i ++ ){
scanf( " %lf%lf " , & point[i].x, & point[i].y);
}
POLY poly = PolygonKernal(n, point);
cout << " Floor # " << cases << endl;
if (poly.n == 0 ) puts( " Surveillance is impossible. " ); // 这里如果有一个点,或者一条线段都可以,所以判断poly.n是不是等于0就行了,不用判断面积
else puts( " Surveillance is possible. " );
cases ++ ;
}
return 0 ;
}
#include < stdio.h >
#include < string .h >
#include < algorithm >
#include < iostream >
using namespace std;
typedef double TYPE;
#define MaxPoint 110
#define Epsilon 1e-10 /*验证* // /精度的范围 ,根据不同的情况调整精度值
// 空间中的点,可以用来作为二维点来用
struct POINT { /* 验证 */
TYPE x; TYPE y; TYPE z;
POINT() : x( 0 ), y( 0 ), z( 0 ) {};
POINT(TYPE _x_, TYPE _y_, TYPE _z_ = 0 )
: x(_x_), y(_y_), z(_z_) {};
// 要用 G++ 提交 ,可以不用这个
POINT operator = ( const POINT & A){
x = A.x;
y = A.y;
z = A.z;
}
};
// 多边形 ,逆时针或顺时针给出x,y
struct POLY { /* 验证 */
// n个点
int n;
// x,y为点的指针,首尾必须重合
TYPE * x;
TYPE * y;
POLY() : n( 0 ), x(NULL), y(NULL) {};
POLY( int _n_, const TYPE * _x_, const TYPE * _y_) {
n = _n_;
x = new TYPE[n + 1 ];
memcpy(x, _x_, n * sizeof (TYPE));
x[n] = _x_[ 0 ];
y = new TYPE[n + 1 ];
memcpy(y, _y_, n * sizeof (TYPE));
y[n] = _y_[ 0 ];
}
};
// 判断 x 是正数还是负数
inline int Sign(TYPE x){ /* 验证 */
return x <- Epsilon ?- 1 :x > Epsilon;
}
void Interect(POINT x,POINT y,TYPE a,TYPE b,TYPE c, int & s,POINT q[]){
TYPE u = fabs(a * x.x + b * x.y + c);
TYPE v = fabs(a * y.x + b * y.y + c);
q[ ++ s].x = (x.x * v + y.x * u) / (u + v);
q[s].y = (x.y * v + y.y * u) / (u + v);
}
// 利用半平面切割
void Cut(TYPE a,TYPE b,TYPE c, int & KarnalPoint,POINT p[])
{
int s = 0 ;
int i;
POINT q[MaxPoint];
for (i = 1 ; i <= KarnalPoint; i ++ ){ // 遍历所有顶点是否能观察到该边
if (Sign(a * p[i].x + b * p[i].y + c) >= 0 ){ // 因为线段是顺时针给出的,如果是逆时针就是<=0
q[ ++ s] = p[i]; // 若是则存储
}
else {
if (Sign(a * p[i - 1 ].x + b * p[i - 1 ].y + c) > 0 ) // 逆时针就是<0
Interect(p[i - 1 ], p[i], a, b, c, s, q);
if (Sign(a * p[i + 1 ].x + b * p[i + 1 ].y + c) > 0 ) // 逆时针就是<0
Interect(p[i + 1 ], p[i], a, b, c, s, q);
}
}
// 最后的p数组存放半平面的点集合
for (i = 1 ;i <= s;i ++ )
p[i] = q[i];
p[s + 1 ] = p[ 1 ],p[ 0 ] = p[s];
KarnalPoint = s;
}
POLY PolygonKernal( int n, POINT point[])
{
int KarnalPoint = n;
POINT p[MaxPoint]; // p 的大小和 tr 的大小一样
for ( int i = 0 ; i < n; i ++ ){
p[i + 1 ] = point[i]; // 初始化边界
}
point[n] = point[ 0 ];
p[n + 1 ] = p[ 1 ];
p[ 0 ] = p[n];
TYPE a,b,c;
for ( int i = 0 ;i < n;i ++ ){
a = point[i + 1 ].y - point[i].y ; // 计算出相邻两点所在直线ax+by+c=0
b = point[i].x - point[i + 1 ].x;
c = point[i + 1 ].x * point[i].y - point[i].x * point[i + 1 ].y;
Cut(a, b, c, KarnalPoint, p);
}
TYPE X[MaxPoint],Y[MaxPoint];
for ( int i = 0 ; i < KarnalPoint; i ++ ){
X[i] = p[i].x;
Y[i] = p[i].y;
}
POLY poly(KarnalPoint, X, Y);
return poly;
}
int main(){
int n,t;
POINT point[MaxPoint];
int cases = 1 ;
while (cin >> n,n != 0 )
{
if (cases != 1 ) puts( "" );
for ( int i = 0 ;i < n;i ++ ){
scanf( " %lf%lf " , & point[i].x, & point[i].y);
}
POLY poly = PolygonKernal(n, point);
cout << " Floor # " << cases << endl;
if (poly.n == 0 ) puts( " Surveillance is impossible. " ); // 这里如果有一个点,或者一条线段都可以,所以判断poly.n是不是等于0就行了,不用判断面积
else puts( " Surveillance is possible. " );
cases ++ ;
}
return 0 ;
}