POJ 1228 判断原始凸包是否唯一

来源:互联网 发布:手机版仓库进销存软件 编辑:程序博客网 时间:2024/06/18 00:19

题意:给出一个去掉几个点后的凸包,判断剩下的几个点组成的新凸包是不是原来的那个凸包。

分析:只要 新凸包的每条边上有3个或3个以上的点时,凸包就是原来那个凸包,

否则凸包不是原来那个凸包。 很好理解的,不是很难想到。

#include<stdio.h>#include<string.h>#include<math.h>#include<algorithm>using namespace std;#define eps 1e-8struct point {int x, y;bool operator < (const point &t) const { //重载<符号return y < t.y || (y == t.y && x < t.x);}} p[1009];int cross(point o, point a, point b) {return (a.x-o.x)*(b.y-o.y)-(a.y-o.y)*(b.x-o.x);}bool dotOnSeg(point a, point b, point c) { // 判断 点c是否在线段ab上return !cross(a, b, c) && (c.x - b.x) * (c.x - a.x)  <= 0&& (c.y-b.y)*(c.y-a.y) <= 0;}int n, m;point st[1009];void graham(point *p, int n, point *st, int &m) {//凸包,起点和终点是同一个点int i;sort(p, p + n);m = 0;for(i = 2; i < n; i++) {while(m >= 2 && cross(st[m-2], st[m-1], p[i]) <= 0)m--;st[m++] = p[i];}int t = m+1;for(i = n - 2; i >= 0; i--) {while(m >= t && cross(st[m-2], st[m-1], p[i]) <= 0)m--;st[m++] = p[i];}}bool judge(point *p, int n, point *st, int m) {if(n <= 5 || m == 1)return 0;int i, j;for(i = 0; i < m-1; i++) {int cnt = 0;for(j = 0; j < n; j++)if(dotOnSeg(st[i], st[i + 1], p[j]))cnt++;if(cnt < 3)return 0;}return 1;}int main() {int i, j, cas;scanf("%d", &cas);while(cas--) {scanf("%d", &n);for(i = 0; i < n; i++)scanf("%d%d", &p[i].x, &p[i].y);graham(p, n, st, m);puts(judge(p, n, st, m) ? "YES" : "NO");}return 0;}


原创粉丝点击