Advertisement
cincout

Сумма Минковского

Apr 3rd, 2019
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.47 KB | None | 0 0
  1.  
  2. #include <iostream>
  3. #include <iomanip>
  4. #include <cmath>
  5. #include <algorithm>
  6. #include <vector>
  7. using namespace std;
  8.  
  9. struct point {
  10. double x, y;
  11. long long len() {
  12. long long X = x;
  13. long long Y = y;
  14. return X * X + Y * Y;
  15. }
  16. void normalize() {
  17. double opr = sqrt(len());
  18. x /= opr, y /= opr;
  19. }
  20. };
  21.  
  22. long long operator * (point& a, point& b) {
  23. long long x1 = a.x;
  24. long long y1 = a.y;
  25. long long x2 = b.x;
  26. long long y2 = b.y;
  27. return x1 * y2 - x2 * y1;
  28. }
  29.  
  30. long long operator ^ (point &a, point& b) {
  31. long long x1 = a.x;
  32. long long y1 = a.y;
  33. long long x2 = b.x;
  34. long long y2 = b.y;
  35. return x1 * x2 + y1 * y2;
  36. }
  37.  
  38. point operator - (point &a, point &b) {
  39. return {a.x - b.x, a.y - b.y};
  40. }
  41.  
  42. point operator + (point &a, point &b) {
  43. return {a.x + b.x, a.y + b.y};
  44. }
  45.  
  46. const int MAXN = 550;
  47. point p[MAXN][MAXN];
  48. point pneg[MAXN][MAXN];
  49.  
  50. point vcs[MAXN][MAXN];
  51. point negvcs[MAXN][MAXN];
  52. point bst[MAXN];
  53. point bstneg[MAXN];
  54.  
  55. int szs[MAXN];
  56. double d[MAXN][MAXN];
  57.  
  58. inline bool cmp1(point &a, point &b) {
  59. if (a.x != b.x)
  60. return a.x < b.x;
  61. return a.y < b.y;
  62. }
  63.  
  64. inline int get_qua(point &a) {
  65. if (a.x >= 0 && a.y >= 0) {
  66. return 2;
  67. }
  68. if (a.x < 0 && a.y >= 0) {
  69. return 3;
  70. }
  71. if (a.x <= 0 && a.y < 0) {
  72. return 4;
  73. }
  74. return 1;
  75. }
  76.  
  77. inline bool cmp2(point &a, point &b) {
  78. int fi = get_qua(a), se = get_qua(b);
  79. if (fi != se)
  80. return fi < se;
  81. if ((a * b) == 0) {
  82. return a.len() < b.len();
  83. }
  84. return (a * b) > 0;
  85. }
  86.  
  87. vector <point> get_mink(vector <point>&a, vector<point> &b) {
  88. vector <point> rx;
  89. for (int i = 1; i < a.size(); ++i) rx.push_back(a[i] - a[i - 1]);
  90. for (int i = 1; i < b.size(); ++i) rx.push_back(b[i] - b[i - 1]);
  91. rx.push_back(a[0] - a.back());
  92. rx.push_back(b[0] - b.back());
  93. vector <point> ret_sum;
  94. ret_sum.push_back(*min_element(a.begin(), a.end(), cmp1) + *min_element(b.begin(), b.end(), cmp1));
  95. sort(rx.begin(), rx.end(), cmp2);
  96. for (auto i : rx) {
  97. ret_sum.push_back(ret_sum.back() + i);
  98. }
  99. return ret_sum;
  100. }
  101.  
  102. struct segment {
  103. point begin, end;
  104. };
  105.  
  106. struct line {
  107. double A, B, C;
  108. };
  109.  
  110. line toline(point& a, point& b) {
  111. line t;
  112. t.A = a.y - b.y;
  113. t.B = b.x - a.x;
  114. t.C = a.x * b.y - b.x * a.y;
  115. return t;
  116. }
  117.  
  118. double get_dist(point& a, line& b) {
  119. double opr = sqrt(b.A * b.A + b.B * b.B);
  120. b.A /= opr, b.B /= opr, b.C /= opr;
  121. return fabs(b.A * a.x + b.B * a.y + b.C);
  122. }
  123.  
  124. bool operator==(point& a, point& b) {
  125. return a.x == b.x && a.y == b.y;
  126. }
  127.  
  128. double get_dist(segment &a, point& b) {
  129. auto zn = (a.begin - a.end) ^ (b - a.end);
  130. auto zn2 = (a.end - a.begin) ^ (b - a.begin);
  131. if (zn >= 0 && zn2 >= 0) {
  132. return get_dist(b, toline(a.begin, a.end));
  133. }
  134. else {
  135. return sqrt(min((b - a.begin).len(), (b - a.end).len()));
  136. }
  137. }
  138.  
  139. double get_dist(int id1, int id2) {
  140. point pred = bst[id1] + bstneg[id2];
  141. double ret = 1e18;
  142. int i1 = 0, i2 = 0;
  143. for (int k = 0; k < szs[id1] + szs[id2]; ++k) {
  144. if (i1 == szs[id1]) {
  145. point cur = pred + negvcs[id2][i2++];
  146. ret = min(ret, get_dist(segment{pred, cur}, point{0, 0}));
  147. pred = cur;
  148. }
  149. else if (i2 == szs[id2]) {
  150. point cur = pred + vcs[id1][i1++];
  151. ret = min(ret, get_dist(segment {pred, cur}, point {0, 0}));
  152. pred = cur;
  153. }
  154. else {
  155. if (cmp2(vcs[id1][i1], negvcs[id2][i2])) {
  156. point cur = pred + vcs[id1][i1++];
  157. ret = min(ret, get_dist(segment {pred, cur}, point {0, 0}));
  158. pred = cur;
  159. }
  160. else {
  161. point cur = pred + negvcs[id2][i2++];
  162. ret = min(ret, get_dist(segment {pred, cur}, point {0, 0}));
  163. pred = cur;
  164. }
  165. }
  166. }
  167. return ret;
  168. }
  169.  
  170. void make(int n) {
  171. for (int i = 0; i < n; ++i) {
  172. d[i][i] = 0;
  173. for (int j = i + 1; j < n; ++j) {
  174. d[i][j] = d[j][i] = get_dist(i, j);
  175. }
  176. }
  177. }
  178.  
  179. void floyd(int n) {
  180. for (int k = 0; k < n; ++k) {
  181. for (int i = 0; i < n; ++i) {
  182. for (int j = 0; j < n; ++j) {
  183. d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
  184. }
  185. }
  186. }
  187. }
  188.  
  189. int main() {
  190. ios::sync_with_stdio(false);
  191. cin.tie(0);
  192. int n, a, b;
  193. cin >> n >> a >> b;
  194. --a, --b;
  195. for (int i = 0; i < n; ++i) {
  196. int sz;
  197. cin >> sz;
  198. szs[i] = sz;
  199. for (int j = 0; j < sz; ++j) {
  200. cin >> p[i][j].x >> p[i][j].y;
  201. pneg[i][j].x = -p[i][j].x;
  202. pneg[i][j].y = -p[i][j].y;
  203. }
  204. for (int j = 0; j + 1 < sz; ++j) {
  205. vcs[i][j] = p[i][j + 1] - p[i][j];
  206. }
  207. vcs[i][sz - 1] = p[i][0] - p[i][sz - 1];
  208. sort(vcs[i], vcs[i] + sz, cmp2);
  209.  
  210. for (int j = 0; j + 1 < sz; ++j) {
  211. negvcs[i][j] = pneg[i][j + 1] - pneg[i][j];
  212. }
  213. negvcs[i][sz - 1] = pneg[i][0] - pneg[i][sz - 1];
  214. sort(negvcs[i], negvcs[i] + sz, cmp2);
  215.  
  216. bst[i] = *min_element(p[i], p[i] + sz, cmp1);
  217. bstneg[i] = *min_element(pneg[i], pneg[i] + sz, cmp1);
  218. }
  219. make(n);
  220. floyd(n);
  221. cout << fixed << setprecision(10);
  222. cout << d[a][b];
  223. return 0;
  224. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement