Advertisement
blufzzz

Fivt_3/task-B/25.11.2017 (2'st test)

Nov 25th, 2017
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.83 KB | None | 0 0
  1. #include <algorithm>
  2. #include <cmath>
  3. #include <iostream>
  4. #include <vector>
  5. #include <cassert>
  6. #include <iterator>
  7.  
  8.  
  9. struct Point {
  10. int x;
  11. int y;
  12. int z;
  13. int number;
  14. Point(int _x, int _y, int _z, int _number = 0):
  15. x(_x),
  16. y(_y),
  17. z(_z),
  18. number(_number)
  19. {
  20. }
  21.  
  22. Point(const Point& other) {
  23. x = other.x;
  24. y = other.y;
  25. z = other.z;
  26. number = other.number;
  27. }
  28. bool operator==(const Point& other) const;
  29. bool operator!=(const Point& other) const;
  30. Point operator-(const Point& other) const;
  31. double operator^(int p) const;
  32. double operator*(const Point& other) const;
  33. double GetModule() const;
  34. void Print() const;
  35. };
  36.  
  37.  
  38. bool Point::operator==(const Point &other) const{
  39. return (this->x == other.x && this->y == other.y && this->z == other.z);
  40. }
  41.  
  42.  
  43. bool Point::operator!=(const Point &other) const{
  44. return (this->x != other.x || this->y != other.y || this->z != other.z);
  45. }
  46.  
  47. Point Point::operator-(const Point& other) const{
  48. return {this->x - other.x, this->y - other.y, this->z - other.z};
  49. }
  50.  
  51.  
  52. double Point::operator^(int p) const{
  53. return std::pow(this->x,p) + std::pow(this->y,p) + std::pow(this->z,p);
  54. }
  55.  
  56.  
  57. double Point::operator*(const Point &other) const{
  58. return (this->x*other.x + this->y*other.y + this->z*other.z);
  59. }
  60.  
  61. Point OtherPointFromSet(const Point& this_point, const std::vector<Point> &points) {
  62. assert(!points.empty());
  63. for(const auto& point: points ) {
  64. if (point != this_point) {
  65. return point;
  66. }
  67. }
  68. }
  69.  
  70. double Point::GetModule() const {
  71. return std::sqrt( this->x*this->x + this->y*this->y + this->z*this->z );
  72. }
  73.  
  74.  
  75. void Point::Print() const {
  76. std::cout<<this->x<<' '<<this->y<<' '<<this->z;
  77. std::cout<<'\n';
  78. }
  79.  
  80.  
  81. Point VectorMultiplication(const Point& p1, const Point& p2) {
  82. return {p1.y*p2.z - p1.z*p2.y, - (p1.x*p2.z - p1.z*p2.x ), p1.x*p2.y - p1.y*p2.x};
  83. }
  84.  
  85. double Distance(const Point& p1, const Point& p2) {
  86. return std::sqrt( (p1-p2)^2 );
  87. }
  88.  
  89.  
  90. double OzAngle(const Point& p1, const Point& p2) {
  91. Point Oz (0,0,1);
  92. Point p12 = p2 - p1;
  93. double t = (p12*Oz)/std::sqrt((p12*p12)*(Oz*Oz));
  94. if (t < -1) {
  95. t = -1;
  96. }
  97. else if(t > 1) {
  98. t = 1;
  99. }
  100. double acos = std::acos(t);
  101. return acos;
  102. }
  103.  
  104.  
  105. Point MostBottom(const std::vector<Point>& points) {
  106. Point point_min = points[0];
  107. for (const auto& point: points) {
  108. if (point.z < point_min.z) {
  109. point_min = point;
  110. }
  111. }
  112. return point_min;
  113. }
  114.  
  115.  
  116. struct Edge {
  117. Point p1;
  118. Point p2;
  119. Point forbidden_point;
  120. bool IsProcessed;
  121. Edge(const Point& _p1, const Point& _p2, const Point& _forbidden_point);
  122. Edge(const Edge& edge, const Point& _forbidden_point);
  123. Edge(const Edge& edge);
  124. Point PivotAroundEdge(const std::vector<Point> &points);
  125. bool operator==(const Edge& other) const;
  126. };
  127.  
  128.  
  129. Edge::Edge(const Point& _p1, const Point& _p2, const Point& _forbidden_point) :
  130. p1(_p1),
  131. p2(_p2),
  132. forbidden_point(_forbidden_point),
  133. IsProcessed(false)
  134. {
  135. }
  136.  
  137.  
  138. Edge::Edge(const Edge& edge, const Point& _forbidden_point) :
  139. p1(edge.p1),
  140. p2(edge.p2),
  141. forbidden_point(_forbidden_point),
  142. IsProcessed(false)
  143. {
  144. }
  145.  
  146. Edge::Edge(const Edge &edge) :
  147. p1(edge.p1),
  148. p2(edge.p2),
  149. forbidden_point(edge.forbidden_point),
  150. IsProcessed(edge.IsProcessed)
  151. {
  152. }
  153.  
  154. bool Edge::operator==(const Edge& other) const{
  155. return (this->p1 == other.p1 && this->p2 == other.p2 ||
  156. this->p1 == other.p2 && this->p2 == other.p1);
  157. }
  158.  
  159.  
  160.  
  161. double FindOutFaceD(double A, double B, double C, const Point& pivot) {
  162. return -( A*pivot.x + B*pivot.y + C*pivot.z );
  163. }
  164.  
  165.  
  166. struct Triangle {
  167. Edge edge12;
  168. Edge edge23;
  169. Edge edge31;
  170. Triangle(const Edge& edge, const Point& point);
  171. Triangle(const Edge& edge1, const Edge& edge2, const Edge& edge3);
  172. std::vector<Edge> GetEdges();
  173. Point GetExternalVector(const std::vector<Point>& points);
  174. std::vector<Point> GetPointsInProperOrder(const std::vector<Point> &points);
  175. };
  176.  
  177. Triangle::Triangle(const Edge& edge, const Point& point) :
  178. edge12(edge, point),
  179. edge23(edge.p1, point, edge.p2),
  180. edge31(edge.p2, point, edge.p1)
  181. {
  182. }
  183.  
  184.  
  185. Triangle::Triangle(const Edge& edge1, const Edge& edge2, const Edge& edge3) :
  186. edge12(edge1),
  187. edge23(edge2),
  188. edge31(edge3)
  189. {
  190. }
  191.  
  192.  
  193. Point GetOtherPoint(const std::vector<Point>& triangles_points, const std::vector<Point> &points) {
  194. assert(triangles_points.size() == 3);
  195. for (const auto& point: points) {
  196. if ((point != triangles_points[1] && point != triangles_points[2])
  197. && point != triangles_points[0]) {
  198. return point;
  199. }
  200. }
  201. }
  202.  
  203.  
  204. std::vector<Point> GetPointsOfTriangle(const Triangle& triangle) {
  205. std::vector<Point> points = { triangle.edge12.p1, triangle.edge12.p2, triangle.edge23.p1,
  206. triangle.edge23.p2, triangle.edge31.p1, triangle.edge31.p2 };
  207. std::sort(points.begin(), points.end(), [](const Point& p1, const Point& p2){ return p1.number <= p2.number ; });
  208. auto last = std::unique(points.begin(), points.end());
  209. points.erase(last, points.end());
  210. return points;
  211. }
  212.  
  213.  
  214. Point Triangle::GetExternalVector(const std::vector<Point>& points) { //O(1)
  215. Triangle this_triangle = *this;
  216. std::vector<Point> triangles_points = GetPointsOfTriangle(this_triangle);
  217. assert(triangles_points.size() == 3);
  218. Point v1 = triangles_points[1] - triangles_points[0];
  219. Point v2 = triangles_points[2] - triangles_points[0];
  220. Point vector_normal_1 = VectorMultiplication(v1,v2);
  221. Point vector_normal_2 = VectorMultiplication(v2,v1);
  222.  
  223. double D_1 = FindOutFaceD(vector_normal_1.x, vector_normal_1.y, vector_normal_1.z, triangles_points[0]);
  224. double D_2 = FindOutFaceD(vector_normal_2.x, vector_normal_2.y, vector_normal_2.z, triangles_points[0]);
  225.  
  226. Point other_point = GetOtherPoint(triangles_points, points); // проверяем только на одной точке
  227.  
  228. if (vector_normal_1*other_point + D_1 < 0) { //приколюшка только для грани!!!
  229. return vector_normal_1;
  230. }
  231. else if (vector_normal_2*other_point + D_2 < 0) {
  232. return vector_normal_2;
  233. }
  234. else {
  235. std::cout<<"Can't Find External Vector for Triangle";
  236. exit(1);
  237. }
  238. }
  239.  
  240.  
  241.  
  242. std::vector<Point> Triangle::GetPointsInProperOrder(const std::vector<Point> &points) {
  243. Triangle this_triangle = *this;
  244. std::vector<Point> triangle_points = GetPointsOfTriangle(this_triangle);
  245. std::vector<Point> proper_order_points;
  246. Point external_normal_vector = this->GetExternalVector(points);
  247. int iter_of_min = 0; //FIX!!!
  248. for (int i = 1; i < triangle_points.size(); ++i) {
  249. if (triangle_points[iter_of_min].number > triangle_points[i].number) {
  250. iter_of_min = i;
  251. }
  252. }
  253. std::swap(triangle_points[iter_of_min],triangle_points[0]);
  254. proper_order_points.push_back(triangle_points[0]);
  255.  
  256. Point v1 = VectorMultiplication(triangle_points[1] - triangle_points[0],external_normal_vector);
  257. Point v2 = VectorMultiplication(triangle_points[2] - triangle_points[0],external_normal_vector);
  258. double D_1 = FindOutFaceD(v1.x , v1.y, v1.z, triangle_points[1]);
  259. double D_2 = FindOutFaceD(v2.x , v2.y, v2.z, triangle_points[2]);
  260. if ( v1*triangle_points[2] + D_1 < 0 ) {
  261. proper_order_points.push_back(triangle_points[1]);
  262. proper_order_points.push_back(triangle_points[2]);
  263. }
  264. else if ( v2*triangle_points[1] + D_2 < 0 ) {
  265. proper_order_points.push_back(triangle_points[2]);
  266. proper_order_points.push_back(triangle_points[1]);
  267. }
  268. else {
  269. std::cout<<"Can't find right order";
  270. exit(1);
  271. }
  272. return proper_order_points;
  273. }
  274.  
  275.  
  276. std::vector<Edge> Triangle::GetEdges() {
  277. return {edge12,edge23,edge31};
  278. }
  279.  
  280.  
  281. double AngleBetweenTriangles(const std::vector<Point>& points, Triangle& first, Triangle& second) {
  282. Point v1 = first.GetExternalVector(points);
  283. Point v2 = second.GetExternalVector(points);
  284. double angle = (v1 * v2)/(v1.GetModule() * v2.GetModule());
  285. return angle;
  286. }
  287.  
  288.  
  289. bool IsFace(Triangle& triangle, const std::vector<Point>& points) { // how to do O(1)
  290. std::vector<Point> triangles_points = GetPointsOfTriangle(triangle);
  291. Point normal = triangle.GetExternalVector(points);
  292.  
  293. double D_of_triangle = FindOutFaceD(normal.x, normal.y, normal.z, triangles_points[0]);
  294. std::vector<double> D_of_other_points;
  295. for (const auto& point: points) {
  296. if ( (point != triangles_points[1] && point != triangles_points[2]) && point != triangles_points[0]) {
  297. double D = FindOutFaceD(normal.x, normal.y, normal.z, point);
  298. D_of_other_points.push_back(D);
  299. }
  300. }
  301. double min_element = *std::min_element(D_of_other_points.begin(), D_of_other_points.end());
  302. double max_element = *std::max_element(D_of_other_points.begin(), D_of_other_points.end());
  303. bool result = (D_of_triangle < min_element ||
  304. D_of_triangle > max_element ) ;
  305. return result;
  306. }
  307.  
  308.  
  309.  
  310. Edge FindEdgeOnHull(const std::vector<Point>& points) {
  311. Point p1 = MostBottom(points);
  312. Point p2 = OtherPointFromSet(p1, points);
  313. for (const auto& point: points) {
  314. if ( p1 != point && OzAngle(p1,point) >= OzAngle(p1,p2) ) {
  315. p2 = point;
  316. }
  317. }
  318. return {p1,p2,p1};
  319. }
  320.  
  321. Triangle FindtTriangleOnHull(std::vector<Point>& points) { //O(n^2)
  322. Edge edge = FindEdgeOnHull(points);
  323. Point pivot = edge.PivotAroundEdge(points);
  324. edge.forbidden_point = pivot;
  325. return {edge, pivot};
  326. }
  327.  
  328.  
  329. //Triangle FindNewTriangle(const std::vector<Point> &points, const Edge& edge) { // need O(n)
  330. // Point p1 = edge.p1;
  331. // Point p2 = edge.p2;
  332. // Point forbidden_point = edge.forbidden_point;
  333. // Triangle based_triangle = Triangle(edge, forbidden_point);
  334. // std::vector<Point> triangle_points = GetPointsOfTriangle(based_triangle);
  335. // Point other_point = GetOtherPoint(triangle_points, points);
  336. // Triangle current_triangle = Triangle(edge, other_point);
  337. //
  338. // for (const auto& point: points) { // need O(n)
  339. // if ((point != p1 && point != p2) && point != forbidden_point) {
  340. // Triangle new_triangle (edge, point);
  341. // if (AngleBetweenTriangles(points, based_triangle, new_triangle) >
  342. // AngleBetweenTriangles(points, based_triangle, current_triangle)) { // O(1)
  343. // current_triangle = new_triangle;
  344. // }
  345. // }
  346. // }
  347. // return current_triangle;
  348. //}
  349.  
  350. Triangle FindNewTriangle(const std::vector<Point> &points, const Edge& edge) {
  351.  
  352. Point p1 = edge.p1;
  353. Point p2 = edge.p2;
  354. Point p3 = edge.forbidden_point;
  355. std::vector<Point> triangle_points = {p1,p2,p3};
  356.  
  357. Point rotate_vector (0,0,0);
  358. Point base_point (0,0,0);
  359. Point normal (0,0,0);
  360.  
  361. Point p1p2 = p2 - p1;
  362. Point p2p1 = p1 - p2;
  363. Point norm_v1 = VectorMultiplication(p1p2,p3-p1);
  364. Point norm_v2 = VectorMultiplication(p2p1,p3-p2);
  365. Point other_point = GetOtherPoint(triangle_points, points);
  366. if (norm_v1*other_point + FindOutFaceD(norm_v1.x, norm_v1.y, norm_v1.z, p1) < 0) {
  367. rotate_vector = p1p2;
  368. base_point = p1;
  369. normal = norm_v1;
  370. }
  371. else if (norm_v2*other_point + FindOutFaceD(norm_v2.x, norm_v2.y, norm_v2.z, p1) < 0) {
  372. rotate_vector = p2p1;
  373. base_point = p2;
  374. normal = norm_v2;
  375. }
  376. else {
  377. std::cout<<" Can't find rotate vector for ";
  378. edge.p1.Print();
  379. edge.p2.Print();
  380. exit(1);
  381. }
  382.  
  383. Point pivot = other_point;
  384. Point current_vector = VectorMultiplication(pivot - base_point, rotate_vector);
  385.  
  386. for (const auto& point: points) { // need O(n)
  387. if ((point != p1 && point != p2) && point != p3) {
  388.  
  389. Point newvector = VectorMultiplication(point - base_point, rotate_vector);
  390. double newcos = (newvector * normal)/(newvector.GetModule() * normal.GetModule());
  391. double currentcos = (current_vector * normal)/(current_vector.GetModule() * normal.GetModule());
  392.  
  393. if ( newcos > currentcos ) { // O(1)
  394. pivot = point;
  395. }
  396. }
  397. }
  398.  
  399. return {edge, pivot};
  400. }
  401.  
  402.  
  403. Point Edge::PivotAroundEdge(const std::vector<Point> &points) { // O(n^2)
  404. Point p1 = this->p1;
  405. Point p2 = this->p2;
  406. for (const auto& point: points) {
  407. if ((point != p1 && point != p2)) {
  408. Edge this_edge = *this;
  409. Triangle triangle (this_edge, point);
  410. if (IsFace(triangle, points)) { // O(n)
  411. return point;
  412. }
  413. }
  414. }
  415. }
  416.  
  417.  
  418. bool IsNotUsedEdges(const std::vector<Edge>& edges) {
  419. bool result = true;
  420. for (auto edge: edges) {
  421. result = result && edge.IsProcessed;
  422. }
  423. return !result;
  424. }
  425.  
  426. template <class T>
  427. bool IsIn(const T& myelement, std::vector<T>& elements) {
  428. for (int i = 0; i < elements.size(); ++i) {
  429. if (myelement == elements[i]) {
  430. elements[i].IsProcessed = true;
  431. return true;
  432. }
  433. }
  434. return false;
  435. }
  436.  
  437.  
  438. void GiftWrapping(std::vector<Point>& points, std::vector<Triangle> & faces) {
  439. Triangle t = FindtTriangleOnHull(points); // O(n^2)
  440. faces.push_back(t);
  441. std::vector<Edge> edges = t.GetEdges();
  442. while (IsNotUsedEdges(edges)) { // O(n)
  443. Edge &newedge = edges.back();
  444. if (!newedge.IsProcessed) {
  445. newedge.IsProcessed = true;
  446. Triangle newtriangle = FindNewTriangle(points, newedge); //O(n) //
  447. std::vector<Edge> triangles_edges = newtriangle.GetEdges();
  448. for (const auto& edge: triangles_edges) {
  449. if (!IsIn(edge, edges)) {
  450. edges.push_back(edge);
  451. }
  452. }
  453. faces.push_back(newtriangle);
  454. }
  455.  
  456. }
  457. }
  458.  
  459.  
  460. void SortByDigit(std::vector<std::vector<int>>& vector, int digit_number) {
  461. std::sort(vector.begin(), vector.end(),
  462. [digit_number](const std::vector<int>& a, const std::vector<int>&b) {
  463. return a[digit_number] < b[digit_number];
  464. });
  465. }
  466.  
  467.  
  468. void Start() {
  469.  
  470. int m; // число тестов
  471. std::cin>>m;
  472.  
  473. for (int i = 0; i < m; ++i) {
  474. int n; // число точек
  475. std::cin>>n;
  476. std::vector<Point> points;
  477. std::vector<Triangle> faces;
  478. for (int j = 0; j < n; ++j) {
  479. int x,y,z;
  480. std::cin>>x>>y>>z;
  481. points.emplace_back(Point(x,y,z,j));
  482. }
  483.  
  484. GiftWrapping(points, faces);
  485.  
  486. std::cout<<faces.size()<<std::endl;
  487.  
  488. std::vector<std::vector<int>> lexic_order(faces.size());
  489. for (int k = 0; k < faces.size(); ++k) {
  490. lexic_order[k].push_back(3);
  491. for (auto point: faces[k].GetPointsInProperOrder(points)) {
  492. lexic_order[k].push_back(point.number);
  493. }
  494. }
  495. // sort
  496. for (int t = lexic_order[0].size() - 1; t > 0 ; --t) {
  497. SortByDigit(lexic_order, t);
  498. }
  499. // output
  500. for (const auto& face: lexic_order) {
  501. for (const auto& number: face) {
  502. std::cout<<number<<' ';
  503. }
  504. std::cout<<'\n';
  505. }
  506. }
  507. }
  508.  
  509.  
  510. bool predicate(const Point& p1, const Point& p2) {
  511. return (p1 == p2);
  512. }
  513.  
  514. int main() {
  515.  
  516. // Point p1 (0,0,0,0);
  517. // Point p2 (10,0,0,1);
  518. // Point p3 (0,10,0,2);
  519. // Point p4 (10,10,10,3);
  520. // Point p5 (5,5,10,4);
  521. //
  522. // std::vector<Point> points = {p1,p2,p3,p4,p5};
  523. // std::vector<Triangle> faces;
  524. // GiftWrapping(points, faces);
  525.  
  526.  
  527. Start();
  528.  
  529. return 0;
  530. }
  531.  
  532. // std::sort(points.begin(), points.end(), [](const Point& p1, const Point& p2){ return p1.number <= p2.number ; });
  533. // auto last = std::unique(points.begin(), points.end());
  534. // points.erase(last, points.end());
  535. //
  536. // for (auto point : points) {
  537. // point.Print();
  538. // }
  539. //
  540. // std::cout<<'\n';
  541. //
  542. // Edge edge(p1,p3,p5);
  543. // Triangle triangle(edge, p5);
  544. // std::vector<Point> point_tr = GetPointsOfTriangle(triangle);
  545. // for (auto point : point_tr) {
  546. // point.Print();
  547. // }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement