题目:pku1228 代码: //方法:凸包问题 //本题大意是已知部分的点,判断这些点所确定的凸包是否唯一 //当已知的点数少于6个时,所确定的凸包肯定不唯一 //当任意一条边上(包括端点)少于3个点,所确定的凸包不唯一 //1 <= n <= 1000 #include <iostream> #include <algorithm> #include <cmath> using namespace std; /*==================================================*/ | Graham 求凸包 O(N * logN) | CALL: nr = graham(pnt, int n, res); res[]为凸包点集; /*==================================================*/ struct point { double x, y; }; bool mult(point sp, point ep, point op) //计算叉积 { return (sp.x - op.x) * (ep.y - op.y) >= (ep.x - op.x) * (sp.y - op.y); } bool operator < (const point &l, const point &r) { return l.y < r.y || (l.y == r.y && l.x < r.x); } int graham(point pnt[], int n, point res[]) { int i, len, k = 0, top = 1; sort(pnt, pnt + n); //需要包含algorithm头文件 if (n == 0) return 0; res[0] = pnt[0]; if (n == 1) return 1; res[1] = pnt[1]; if (n == 2) return 2; res[2] = pnt[2]; for (i = 2; i < n; i++) //左链 { while (top && mult(pnt[i], res[top], res[top-1])) top--; res[++top] = pnt[i]; } len = top; res[++top] = pnt[n - 2]; for (i = n - 3; i >= 0; i--) //右链 { while (top!=len && mult(pnt[i], res[top],res[top-1])) top--; res[++top] = pnt[i]; } return top; // 返回凸包中点的个数 } //判断点p是否在以la,lb为端点的线段上 bool p_in_line(point p,point la,point lb) { return (p.x-la.x)*(lb.y-la.y)==(p.y-la.y)*(lb.x-la.x); } int main() { int t,n,m; int i,j,k; point p[1005],res[1005]; cin>>t; while(t--) { cin>>n; for(i=0;i<n;i++) cin>>p[i].x>>p[i].y; if(n<=5){cout<<"NO"<<endl;continue;} m=graham(p,n,res); for(i=0;i<m;i++) { k=0; for(j=0;j<n;j++) { if(p_in_line(p[j],res[i],res[(i+1)%m]))k++; } if(k<3) { cout<<"NO"<<endl;break; } } if(i==m) cout<<"YES"<<endl; } return 0; }