[POJ][1228][Grandpa's Estate]

题目:http://poj.org/problem?id=1228

题意:给定一些点,求能否确定一个凸包。如果在这些点中求出的凸包的每一条边都至少有三个点(包括顶点),则这个凸包是确定的。

    注意一条直线或点数n<5时应输出NO。

View Code
#include <stdio.h>
#include
<math.h>
#include
<string.h>
#include
<iostream>
#include
<algorithm>

using namespace std;
const double eps = 1e-8;
const double pi = acos(-1.0);

typedef
struct
{
double x, y;
}cpoint;

double sqr(double x) {return x*x;}

double dcmp(double x)
{
if(x < -eps) return -1; else return x > eps;
}

double cross(cpoint p0, cpoint p1, cpoint p2)
{
return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
}

double dot(cpoint p0, cpoint p1, cpoint p2)
{
return (p1.x - p0.x) * (p2.x - p0.x) + (p1.y - p0.y) * (p2.y - p0.y);
}

double dis(cpoint p1, cpoint p2)
{
return sqrt(sqr(p1.x - p2.x) + sqr(p1.y - p2.y));
}

double dissqr(cpoint p1, cpoint p2)
{
return sqr(p1.x - p2.x) + sqr(p1.y - p2.y);
}

int PointEqual(const cpoint p1, const cpoint p2)
{
return dcmp(p1.x - p2.x) == 0 && dcmp(p1.y - p2.y) == 0;
}

int PointOnSegment(cpoint p0, cpoint p1, cpoint p2)
{
return dcmp(cross(p0, p1, p2)) == 0 && dcmp(dot(p0, p1, p2)) <= 0;
}

cpoint bp;

int PolarCmp(const cpoint &p1, const cpoint &p2)
{
int u = dcmp(cross(bp, p1, p2));
return u > 0 || (u == 0 && dcmp(dissqr(bp, p1)-dissqr(bp, p2)) < 0);
}

int PointInPolygon(cpoint cp, cpoint p[], int n)
{
int i, k, d1, d2, wn = 0;
double sum = 0;
p[n]
= p[0];
for (int i = 0; i < n; i++)
{
if (PointOnSegment(cp, p[i], p[i+1])) return 2;
k
= dcmp(cross(p[i], p[i+1], cp));
d1
= dcmp(p[i+0].y - cp.y);
d2
= dcmp(p[i+1].y - cp.y);
if (k > 0 && d1 <= 0 && d2 > 0) wn++;
if (k < 0 && d2 <= 0 && d1 > 0) wn--;
}
return wn != 0;
}

void graham(cpoint pin[], int n, cpoint ch[], int &m)
{
int i, j, k, u, v;
memcpy(ch, pin, n
*sizeof(cpoint));
for (i = k = 0; i < n; i++)
{
u
= dcmp(ch[i].x - ch[k].x);
v
= dcmp(ch[i].y - ch[k].y);
if (v < 0 || (v == 0 && u < 0)) k = i;
}
bp
= ch[k];
sort(ch, ch
+ n, PolarCmp);
n
= unique(ch, ch + n, PointEqual) - ch;
if (n <= 1) {m = n; return ;}
if (dcmp(cross(ch[0], ch[1], ch[n-1])) == 0)
{
m
= 2; ch[1] = ch[n-1]; return ;
}
ch[n
++] = ch[0];
for (i = 1, j = 2; j < n; j++)
{
while (i > 0 && dcmp(cross(ch[i-1], ch[i], ch[j])) <= 0) i--;
ch[
++i] = ch[j];
}
m
= i;
}

double PolygononArea(cpoint p[], int n)
{
if (n < 3) return 0;
double s = p[0].y * (p[n-1].x - p[1].x);
for (int i = 1; i<n; i++)
{
s
+= p[i].y * (p[i-1].x - p[(i+1) % n].x);
}
return fabs(s / 2.0);
}

double LengthOfPolygon(cpoint p[], int m)
{
double length = 0;
for (int i=0; i<m; i++)
{
length
+= dis(p[i], p[(i+1)%m]);
}
return length;
}

cpoint kingdom[
1005];
cpoint polygon_kingdom[
1005];
int m, v[1005], segment[1005];

int main()
{
//freopen("D:/a.txt", "r", stdin);
int ncase, n;
scanf(
"%d", &ncase);
for (int k=0; k<ncase; k++)
{
memset(v,
0, sizeof(v));
memset(segment,
0, sizeof(segment));
scanf(
"%d", &n);
for (int i=0; i<n; i++)
{
scanf(
"%lf%lf", &kingdom[i].x, &kingdom[i].y);
}
graham(kingdom, n, polygon_kingdom, m);
int stop = 0;
for (int i=0; i<n; i++)
{
if (PointInPolygon(kingdom[i], polygon_kingdom, m) == 1)
{
printf(
"NO\n");
stop
= 1;
break;
}
}
if (stop) continue;
for (int i=0; i<m; i++)
{
for (int j=0; j<n; j++)
{
if (v[j]) continue;
if (PointEqual(kingdom[j], polygon_kingdom[i])) {v[j]=1;continue;}
if (PointEqual(kingdom[j], polygon_kingdom[(i+1)%m])) {v[j]=1;continue;}
if (PointOnSegment(kingdom[j], polygon_kingdom[(i+1)%m], polygon_kingdom[i])){segment[i]=1; continue;}
}
}
int sum = 0;
for (int i=0; i<m; i++)
{
sum
+= segment[i];
}
if (n < 6){printf("NO\n"); continue;}
if (m <= 2){printf("NO\n"); continue;}
if (m == sum) printf("YES\n");
else printf("NO\n");
}
return 0;
}
原文地址:https://www.cnblogs.com/nigel0913/p/2172395.html