Advertisement
Mlxa

Касательные к многоугольнику

Mar 31st, 2019
251
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.26 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. using type = long double;
  3. #define equal equal_
  4. #define less less_
  5. #define greater greater_
  6. #define double type
  7. #define long int64_t
  8. using namespace std;
  9.    
  10. const double PI = atan2((double)0, (double)-1);
  11.    
  12. const double eps = 1e-12;
  13. const double inf = 1e+12;
  14.    
  15. bool equal(double a, double b) {
  16.     return abs(a - b) <= eps;
  17. }
  18.    
  19. bool less(double a, double b) {
  20.     return a < b - eps;
  21. }
  22.    
  23. bool greater(double a, double b) {
  24.     return a > b + eps;
  25. }
  26.    
  27.    
  28. struct point {
  29.     double x, y;
  30.        
  31.     point(double a, double b) :
  32.         x(a),
  33.         y(b) {}
  34.        
  35.     point() :
  36.         point(0, 0) {}
  37.        
  38.     point to(point v) {
  39.         return {v.x - x, v.y - y};
  40.     }
  41.        
  42.     point operator+(point v) {
  43.         return {v.x + x, v.y + y};
  44.     }
  45.        
  46.     point operator-(point v) {
  47.         return {x - v.x, y - v.y};
  48.     }
  49.        
  50.     double operator*(point v) {
  51.         return x * v.x + y * v.y;
  52.     }
  53.        
  54.     double operator%(point v) {
  55.         return x * v.y - y * v.x;
  56.     }
  57.        
  58.     double angle() {
  59.         return atan2(y, x);
  60.     }
  61.        
  62.     friend double angle(point a, point b) {
  63.         return atan2(a % b, a * b);
  64.     }
  65.        
  66.     double len2() {
  67.         return x * x + y * y;
  68.     }
  69.        
  70.     double len() {
  71.         return sqrt(len2());
  72.     }
  73.        
  74.     double dist2(point p) {
  75.         return to(p).len2();
  76.     }
  77.        
  78.     double dist(point p) {
  79.         return sqrt(dist2(p));
  80.     }
  81.        
  82.     bool small(point a, point b) {
  83.         return !less(to(a) * to(b), 0);
  84.     }
  85.        
  86.     bool operator==(point p) {
  87.         return equal(x, p.x) && equal(y, p.y);
  88.     }
  89.        
  90.     bool operator!=(point p) {
  91.         return !(operator==(p));
  92.     }
  93.        
  94.     bool lt(point a, point b) {
  95.         return greater(to(a) % to(b), 0);
  96.     }
  97.        
  98.     bool rt(point a, point b) {
  99.         return less(to(a) % to(b), 0);
  100.     }
  101.        
  102.     friend istream &operator>>(istream &in, point &p) {
  103.         return in >> p.x >> p.y;
  104.     }
  105.        
  106.     friend ostream &operator<<(ostream &out, point p) {
  107.         return out << p.x << " " << p.y;
  108.     }
  109. };
  110.    
  111. struct line {
  112.     point f, s;
  113.        
  114.     line(point a, point b) :
  115.         f(a),
  116.         s(b) {
  117.         assert(a != b);
  118.     }
  119.        
  120.     line() :
  121.         f(),
  122.         s() {}
  123.        
  124.     double dist2(point p) {
  125.         double sq = p.to(f) % p.to(s);
  126.         return sq * sq / f.dist2(s);
  127.     }
  128.        
  129.     double dist(point p) {
  130.         return p.to(f) % p.to(s) / f.dist(s);
  131.     }
  132.        
  133.     bool have(point p) {
  134.         return equal(f.to(p) % f.to(s), 0);
  135.     }
  136. };
  137.    
  138. struct segment {
  139.     point f, s;
  140.        
  141.     segment(point a, point b) :
  142.         f(a),
  143.         s(b) {}
  144.        
  145.     segment() :
  146.         f(),
  147.         s() {}
  148.        
  149.     double dist2(point p) {
  150.         if (f == s) {
  151.             return f.dist2(p);
  152.         }
  153.         if (f.small(p, s) && s.small(p, f)) {
  154.             return line(f, s).dist2(p);
  155.         } else {
  156.             return min(p.dist2(f), p.dist2(s));
  157.         }
  158.     }
  159.        
  160.     double dist(point p) {
  161.         return sqrt(dist2(p));
  162.     }
  163.        
  164.     bool have(point p) {
  165.         return line(f, s).have(p) && !greater(p.to(f) * p.to(s), 0);
  166.     }
  167.        
  168.     bool check_intersect(segment o) {
  169.         if (have(o.f) || have(o.s) || o.have(f) || o.have(s)) {
  170.             return true;
  171.         }
  172.         point a = f;
  173.         point b = s;
  174.         point c = o.f;
  175.         point d = o.s;
  176.         return  less((a.to(b) % a.to(c)) * (a.to(b) % a.to(d)), 0) &&
  177.                 less((c.to(d) % c.to(a)) * (c.to(d) % c.to(b)), 0);
  178.     }
  179.        
  180.     double dist2(segment o) {
  181.         if (check_intersect(o)) {
  182.             return 0;
  183.         }
  184.         double a = dist2(o.f);
  185.         double b = dist2(o.s);
  186.         double c = o.dist2(f);
  187.         double d = o.dist2(s);
  188.         return min({a, b, c, d});
  189.     }
  190.        
  191.     double dist(segment o) {
  192.         return sqrt(dist2(o));
  193.     }
  194. };
  195.    
  196. const int maxn = 2e5 + 64;
  197. int n, k;
  198. point p[maxn];
  199. double d[maxn];
  200.    
  201. point getp(int i) {
  202.     i = (i + n) % n;
  203.     return p[i];
  204. }
  205.  
  206. int left_tan(point q) {
  207.     #define vis(i) (q.rt(p[i], p[i + 1]))
  208.     if (!vis(n - 1) && vis(0)) {
  209.         return 0;
  210.     }
  211.     int l = 0, r = n;
  212.     if (vis(0)) {
  213.         while (r - l > 1) {
  214.             int m = (l + r) / 2;
  215.             if (q.lt(p[0], p[m])) {
  216.                 if (vis(m)) {
  217.                     r = m;
  218.                 } else {
  219.                     l = m;
  220.                 }
  221.             } else {
  222.                 l = m;
  223.             }
  224.         }
  225.     } else {
  226.         while (r - l > 1) {
  227.             int m = (l + r) / 2;
  228.             if (q.lt(p[0], p[m])) {
  229.                 if (vis(m)) {
  230.                     r = m;
  231.                 } else {
  232.                     l = m;
  233.                 }
  234.             } else {
  235.                 r = m;
  236.             }
  237.         }
  238.     }
  239.     assert(r < n);
  240.     return r;
  241. }
  242.    
  243. int right_tan(point q) {
  244.     if (vis(n - 1) && !vis(0)) {
  245.         return 0;
  246.     }
  247.     int l = 0, r = n - 1;
  248.     if (vis(0)) {
  249.         while (r - l > 1) {
  250.             int m = (l + r) / 2;
  251.             if (q.rt(p[0], p[m])) {
  252.                 if (vis(m)) {
  253.                     l = m;
  254.                 } else {
  255.                     r = m;
  256.                 }
  257.             } else {
  258.                 r = m;
  259.             }
  260.         }
  261.     } else {
  262.         while (r - l > 1) {
  263.             int m = (l + r) / 2;
  264.             //cerr << "m = " << m << endl;
  265.             if (q.rt(p[0], p[m])) {
  266.                 if (vis(m)) {
  267.                     l = m;
  268.                 } else {
  269.                     r = m;
  270.                 }
  271.             } else {
  272.                 l = m;
  273.             }
  274.         }
  275.     }
  276.     assert(r < n);
  277.     return r;
  278.     #undef vis
  279. }
  280.    
  281. int main() {
  282. #ifdef LC
  283.     assert(freopen("input.txt", "r", stdin));
  284. #else
  285.     assert(freopen("princess.in", "r", stdin));
  286.     assert(freopen("princess.out", "w", stdout));
  287. #endif
  288.     ios::sync_with_stdio(0);
  289.     cin.tie(0);
  290.     cout << fixed << setprecision(15);
  291.     cerr << fixed << setprecision(15);
  292.        
  293.     cin >> n >> k;
  294.     --k;
  295.     for (int i = 0; i < n; ++i) {
  296.         cin >> p[i];
  297.         p[i + n] = p[i];
  298.     }
  299.     fill_n(d, maxn, inf);
  300.     d[k] = 0;
  301.     for (int i = k + 1; i < n; ++i) {
  302.         d[i] = min(d[i], d[i - 1] + p[i].dist(p[i - 1]));
  303.     }
  304.     d[0] = min(d[0], d[n - 1] + p[0].dist(p[n - 1]));
  305.     for (int i = 1; i < k; ++i) {
  306.         d[i] = min(d[i], d[i - 1] + p[i].dist(p[i - 1]));
  307.     }
  308.     for (int i = k - 1; i >= 0; --i) {
  309.         d[i] = min(d[i], d[i + 1] + p[i].dist(p[i + 1]));
  310.     }
  311.     d[n - 1] = min(d[n - 1], d[0] + p[n - 1].dist(p[0]));
  312.     for (int i = n - 2; i > k; --i) {
  313.         d[i] = min(d[i], d[i + 1] + p[i].dist(p[i + 1]));
  314.     }
  315.        
  316.     int m;
  317.     cin >> m;
  318.     while (m--) {
  319.         point q;
  320.         cin >> q;
  321.         int i = left_tan(q);
  322.         int j = right_tan(q);
  323.         if (!q.lt(p[k], getp(k + 1))) {
  324.             cout << q.dist(p[k]) << "\n";
  325.         } else {
  326.             cout << min(q.dist(p[i]) + d[i], q.dist(p[j]) + d[j]) << "\n";
  327.         }
  328.     }
  329.      
  330.     /*point q;
  331.     while (cin >> q) {
  332.         cout << right_tan(q) << endl;
  333.     }*/
  334.      
  335.     return 0;
  336. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement