zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    mysql无法启动-You may have to recover from a backup
    mysql导出索引sql 导出索引创建语句
    Padavan路由器设置桥接多路由器同WIFI方法
    挖的坑还是要填的
    I'm Back
    40行加速头文件
    一些XJOI博客的密码
    p进制线性基填坑
    Dirichelet卷积的k次方根
    用pb_ds写一颗线段树
  • 原文地址:https://www.cnblogs.com/yijiull/p/7677655.html
Copyright © 2011-2022 走看看