poj1228

题目链接:http://acm.pku.edu.cn/JudgeOnline/problem?id=1228

题意:题目输入一个凸包上的点(没有凸包内部的点,要么是凸包顶点,要么是凸包边上的点),判断这个凸包是否稳定。所谓稳定就是判断能不能在原有凸包上加点,

         得到一个更大的凸包,并且这个凸包包含原有凸包上的所有点。

         很容易得到,当一个凸包稳定时,凸包的每条边上都要有至少三个点,若只有两个点,则可以增加一个点,得到更大的凸包。

思路:直接求凸包,得到原来凸包顶点,去掉凸包边上的点,由于求凸包的过程中要对点集pnt[]极角排序,最后只需判断求得的凸包上的点在排序后的pnt[]中是否相邻,

         凸包中第一个和最后一个点还需特别判断一下它们之间是否有点,若求得凸包中的点个数为2,则输入的所有点都在一条线上,这时需输出NO

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;

const double eps = 1e-8;
struct Point {
    double x, y;
} pnt[1005];

int stk[1005], top;

int dblcmp(double k) {
    if (fabs(k) < eps) return 0;
    return k > 0 ? 1 : -1;
}

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

double getDis(Point a, Point b) {
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

bool cmp(const Point& a, const Point& b) {
    int d = dblcmp(multi(pnt[0], a, b));
    if (!d) return getDis(pnt[0], a) < getDis(pnt[0], b);
    return d > 0;
}

int main()
{
    int t, n, i, k;
    double tx, ty;

    scanf ("%d", &t);
    while (t--) {
        scanf ("%d", &n);
        scanf ("%lf%lf", &pnt[0].x, &pnt[0].y);
        tx = pnt[0].x; ty = pnt[0].y;
        k = 0;
        for (i = 1; i < n; i++) {
            scanf ("%lf%lf", &pnt[i].x, &pnt[i].y);
            int d = dblcmp(ty-pnt[i].y);
            if (d > 0) {
                k = i;
                tx = pnt[i].x;
                ty = pnt[i].y;
            }
            else if (!d && dblcmp(tx-pnt[i].x) > 0) {
                k = i;
                tx = pnt[i].x;
            }
        }
        pnt[k].x = pnt[0].x;
        pnt[k].y = pnt[0].y;
        pnt[0].x = tx;
        pnt[0].y = ty;

        sort(pnt+1, pnt+n, cmp);
        stk[0] = 0;
        stk[1] = 1;
        top = 1;
        for (i = 2; i < n; i++) {
            while (top >= 1 && dblcmp(multi(pnt[stk[top-1]], pnt[i], pnt[stk[top]])) >= 0) top--;
            stk[++top] = i;
        }
        if (top <= 1) {
            printf ("NO\n");
            continue;
        }
        bool flag = false;
        for (i = 1; i <= top; i++)
            if (stk[i]-stk[i-1] == 1) {
                flag = true;
                break;
            }
        for (i = 1; i < n-1; i++)
            if (!dblcmp(multi(pnt[0], pnt[i], pnt[n-1]))) break;
        if (!flag && i < n-1) printf ("YES\n");
        else printf ("NO\n");
    }
    return 0;
}

你可能感兴趣的:(poj1228)