CRB and Farm HDU

CRB and Farm

HDU - 5408
题意:给一个n个点的大凸包,再给k个内部点,问能否选择不超过2k个大凸包上的点使得所选点围成的凸包完全包含内部的k个点.
首先明确一定是存在的
可以先对内部的k个点求一个凸包,然后选一个凸包内的点A,求A与凸包上的各点形成的射线与大凸包的交点.则交点所在线段的两端就是所选点.
 
关键在于判断射线与线段相交.
//判断射线a1--b1是否与线段a2--b2相交
bool Intersection(Point a1, Point b1, Point a2, Point b2) { 
    double c1 = Cross(b1-a1, a2-a1), c2 = Cross(b1-a2, b2-a2);
    double c3 = Cross(b1-b2, a1-b2);
    return dcmp(c1)<0 && dcmp(c2)<0 && dcmp(c3)<0 ||
           dcmp(c1)>0 && dcmp(c2)>0 && dcmp(c3)>0;
  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 const int inf = 0x3f3f3f3f;
  4 const double eps = 1e-8;
  5 const int maxn = 2e5+10;
  6 
  7 struct Point {
  8     double x,y;
  9     Point (double x = 0, double y = 0) : x(x), y(y) {}
 10 };
 11 typedef Point Vector;
 12 Vector operator + (Vector a, Vector b) {
 13     return Vector (a.x + b.x, a.y + b.y);
 14 }
 15 Vector operator * (Vector a, double s) {
 16     return Vector (a.x * s, a.y * s);
 17 }
 18 Vector operator / (Vector a, double p) {
 19     return Vector (a.x / p, a.y / p);
 20 }
 21 Vector operator - (Point a, Point b) {
 22     return Vector (a.x - b.x, a.y - b.y);
 23 }
 24 bool operator < (Point a, Point b) {
 25     return a.x < b.x || (a.x == b.x && a.y < b.y);
 26 }
 27 int dcmp (double x) {
 28     if(fabs(x) < eps) return 0;
 29     return x < 0 ? -1 : 1;
 30 }
 31 bool operator == (const Point &a, const Point &b) {
 32     return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
 33 }
 34 
 35 double Dot(Vector a, Vector b) {
 36     return a.x * b.x + a.y * b.y;
 37 }
 38 double Length (Vector a) {
 39     return sqrt(Dot(a, a));
 40 }
 41 double Angle (Vector a, Vector b) {
 42     return acos(Dot(a, b) / Length(a) / Length(b));
 43 }
 44 double Cross (Vector a, Vector b) {
 45     return a.x * b.y - a.y * b.x;
 46 }
 47 //判断射线a1--b1是否与线段a2--b2相交
 48 bool Intersection(Point a1, Point b1, Point a2, Point b2) { 
 49     double c1 = Cross(b1-a1, a2-a1), c2 = Cross(b1-a2, b2-a2);
 50     double c3 = Cross(b1-b2, a1-b2);
 51     return dcmp(c1)<0 && dcmp(c2)<0 && dcmp(c3)<0 ||
 52            dcmp(c1)>0 && dcmp(c2)>0 && dcmp(c3)>0;
 53 }
 54 //凸包
 55 int ConvexHull(Point *p, int n, Point *ch) {
 56     int m = 0;
 57     sort(p, p+n);
 58     for(int i = 0; i < n; i++) {
 59         while(m > 1 && Cross(ch[m-1] - ch[m-2], p[i] - ch[m-2]) <= 0) m--;  //去掉在边上的点
 60         ch[m++] = p[i];
 61     }
 62     int k = m;
 63     for(int i = n-2; i >= 0; i--) {
 64         while(m > k && Cross(ch[m-1] - ch[m-2], p[i] - ch[m-2]) <= 0) m--;  //
 65         ch[m++] = p[i];
 66     }
 67     if(m > 1) m--;
 68     return m;
 69 }
 70 
 71 Point p1[maxn], p2[maxn], ch[maxn];
 72 
 73 int main() {
 74     int t;
 75     //freopen("in.txt", "r", stdin);
 76     scanf("%d", &t);
 77     while(t--){
 78         int n;
 79         scanf("%d", &n);
 80         for(int i = 0; i < n; i++) {
 81             scanf("%lf %lf", &p1[i].x, &p1[i].y);
 82         }
 83         p1[n] = p1[0];
 84         int k;
 85         scanf("%d", &k);
 86         for(int i = 0; i < k; i++){
 87             scanf("%lf %lf", &p2[i].x, &p2[i].y);
 88         }
 89         int cnt = ConvexHull(p2, k, ch);
 90         Point o = ch[0];
 91         vector<int> v;
 92         for(int i = 1; i < cnt; i++) {
 93             o = (o+ch[i])/2;
 94         }
 95         int id = 0;
 96         for(int i = 0; i < cnt; i++){
 97             while(!Intersection(o, ch[i], p1[id], p1[id+1])) id=(id+1)%n;
 98             v.push_back(id);
 99             v.push_back((id+1)%n);
100         }
101         sort(v.begin(), v.end());
102         cnt = unique(v.begin(), v.end()) - v.begin();
103         puts("Yes");
104         printf("%d
", cnt);
105         for(int i = 0; i < cnt; i++) printf("%d%c", v[i]+1, i==cnt-1?'
':' '); 
106     }
107 }
View Code
原文地址:https://www.cnblogs.com/yijiull/p/7677655.html