题意:爷爷的农场是一个用大钉打点确定凸包,但是有些大钉不见了, 输入现存的N个刚好构成凸包的点, 求这些点能否唯一确定一个凸包。
分析:1.如果凸包边上至少含有一点, 则凸包可以唯一确定, 因为在凸包边上的外围加上一个点, 则凸包会多出一个不在凸包上的点。
2. 如果点都共线, 则外围凸包上可以随便放一个或多个点, 凸包不确定。
#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <complex>
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <string>
#define INF 1e8
#define MAX (int)1e6+ 5
#define eps 1e-8
using namespace std;
int T, n;
inline int next(const int &i, const int &n){ return (i + 1) % n;}
inline int cmpd(double x){ return x > eps ? 1: (x < -eps? -1 : 0 );}
struct Point{
int x, y;
Point (){}
Point (const int &xx, const int &yy):x(xx),y(yy){}
friend int det(const Point &a, const Point &b){
return a.x * b.y - a.y * b.x;
}
friend int dot(const Point &a, const Point &b){
return a.x * b.x + a.y * b.y;
}
Point operator - (const Point &a)const{
return Point(x - a.x, y - a.y);
}
bool operator == (const Point &a)const {
return a.x == x && a.y == y;
}
bool operator < (const Point &a)const {
return x < a.x || ( x == a.x && y < a.y);
}
void in(){
cin>>x>>y;
}
void out(){
cout<<x<<y<<endl;
}
};
struct Line{
Point s, t;
Line(const Point &ss, const Point &tt):s(ss), t(tt){}
bool isInLineEx(const Point &p){
int res1 = det(p - s, p - t);///共线
int res2 = dot(p - s, p - t);///不在两端
return res1 == 0 && res2 < 0;
}
};
struct Polygon{
vector<Point> p;
Polygon(){}
Polygon(const vector<Point> &ip):p(ip){}
double area(){
int n = p.size();
double ans = 0;
for(int i = 0; i < n; i++){
ans += det(p[i], p[next(i, n)]);
}
ans /= 2.0;
return ans;
}
bool hull(vector<Point> &t){
int n = t.size(), m = 0;
p.resize(n);
sort(t.begin(), t.end());
t.erase(unique(t.begin(), t.end()), t.end());//去重复
n = t.size();
bool isThree = false;
for(int i = 0; i < n ;i++){
while( m > 1 && det(p[m - 1] - p[m - 2], p[m - 1] - t[i]) <= 0 )m--;//replaced
p[m++] = t[i];
}
int k = m;
for(int i = n - 2; i >= 0; i--){
while(m > k && det(p[m - 1] - p[m - 2], p[m - 1] - t[i]) <= 0)m--;
p[m++] = t[i];
}
p.resize(m);/// 0 - (m - 1) - 0
// for(int i = 0; i < m - 1; i++){
// p[i].out();
// }
if(cmpd(area()) == 0){return false;}
for(int i = 0; i < m - 1; i++){
bool isFind = false;
Line line(p[i], p[i + 1]);
for(int j = 0; j < n; j++){
if(line.isInLineEx(t[j]) ){
isFind = true;
break;
}
}if(!isFind){return false;}
}
return true;
}
};
int main()
{
cin>>T;
while(T--){
cin>>n;
vector<Point>temp;
Point t;
for(int i = 0; i < n; i++){
t.in(); temp.push_back(t);
}
Polygon pg;
if(pg.hull(temp))puts("YES");
else puts("NO");
}
return 0;
}
/*
5
6
0 0
0 1
0 2
1 0
2 0
1 1
*/