Advertisement
blufzzz

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

Nov 25th, 2017
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.66 KB | None | 0 0
  1. #include <algorithm>
  2. #include <cmath>
  3. #include <iostream>
  4. #include <vector>
  5. #include <iterator>
  6.  
  7.  
  8. struct Point {
  9.     int  x;
  10.     int  y;
  11.     int  z;
  12.     int number;
  13.     Point(int _x, int _y, int _z, int _number = 0):
  14.             x(_x),
  15.             y(_y),
  16.             z(_z),
  17.             number(_number)
  18.     {
  19.     }
  20.  
  21.     Point(const Point& other) {
  22.         x = other.x;
  23.         y = other.y;
  24.         z = other.z;
  25.         number = other.number;
  26.     }
  27.     bool operator==(const Point& other) const;
  28.     bool operator!=(const Point& other) const;
  29.     Point operator-(const Point& other) const;
  30.     double operator^(int p) const;
  31.     double operator*(const Point& other) const;
  32.     double GetModule() const;
  33.     void Print() const;
  34. };
  35.  
  36.  
  37. bool Point::operator==(const Point &other) const{
  38.     return (this->x == other.x && this->y == other.y && this->z == other.z);
  39. }
  40.  
  41.  
  42. bool Point::operator!=(const Point &other) const{
  43.     return (this->x != other.x || this->y != other.y || this->z != other.z);
  44. }
  45.  
  46. Point Point::operator-(const Point& other) const{
  47.     return {this->x - other.x, this->y - other.y, this->z - other.z};
  48. }
  49.  
  50.  
  51. double Point::operator^(int p) const{
  52.     return std::pow(this->x,p) + std::pow(this->y,p) + std::pow(this->z,p);
  53. }
  54.  
  55.  
  56. double Point::operator*(const Point &other) const{
  57.     return (this->x*other.x + this->y*other.y + this->z*other.z);
  58. }
  59.  
  60. Point OtherPointFromSet(const Point& this_point, const std::vector<Point> &points) {
  61.     if (points.empty()) {
  62.         std::cerr<<" points is empty";
  63.         exit(1);
  64.     }
  65.     for(const auto& point: points ) {
  66.         if (point != this_point) {
  67.             return point;
  68.         }
  69.     }
  70.     std::cerr<<"NO OtherPointFromSet";
  71.     exit(1);
  72. }
  73.  
  74. double Point::GetModule() const {
  75.     return std::sqrt( this->x*this->x + this->y*this->y + this->z*this->z );
  76. }
  77.  
  78.  
  79. void Point::Print() const {
  80.     std::cout<<this->x<<' '<<this->y<<' '<<this->z;
  81.     std::cout<<'\n';
  82. }
  83.  
  84.  
  85. Point VectorMultiplication(const Point& p1, const Point& p2) {
  86.     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};
  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.     if(triangles_points.size() < 3) {
  195.         std::cerr<<" triangles_points.size() < 3 ";
  196.         exit(1);
  197.     }
  198.     for (const auto& point: points) {
  199.         if ((point != triangles_points[1] && point != triangles_points[2])
  200.             && point != triangles_points[0]) {
  201.             return point;
  202.         }
  203.     }
  204.     std::cerr<<"NO OtherPoint for Triangles";
  205.     exit(1);
  206. }
  207.  
  208.  
  209. std::vector<Point> GetPointsOfTriangle(const Triangle& triangle) {  //catch!!!
  210.     std::vector<Point> points = { triangle.edge12.p1, triangle.edge12.p2, triangle.edge23.p1,
  211.                                   triangle.edge23.p2, triangle.edge31.p1, triangle.edge31.p2 };
  212.     std::sort(points.begin(), points.end(), [](const Point& p1, const Point& p2){ return p1.number <= p2.number  ; });
  213.     auto last = std::unique(points.begin(), points.end());
  214.     points.erase(last, points.end());
  215.     return points;
  216. }
  217.  
  218.  
  219. Point Triangle::GetExternalVector(const std::vector<Point>& points) { //O(1)
  220.     Triangle this_triangle = *this;
  221.     std::vector<Point> triangles_points = GetPointsOfTriangle(this_triangle);
  222.  
  223.     if (triangles_points.size() < 3) {
  224.         std::cerr<<" triangles_points.size() < 3 ";
  225.         exit(1);
  226.     }
  227.  
  228.     Point v1 = triangles_points[1] - triangles_points[0];
  229.     Point v2 = triangles_points[2] - triangles_points[0];
  230.     Point vector_normal_1 = VectorMultiplication(v1,v2);
  231.     Point vector_normal_2 = VectorMultiplication(v2,v1);
  232.  
  233.     double D_1 = FindOutFaceD(vector_normal_1.x, vector_normal_1.y, vector_normal_1.z, triangles_points[0]);
  234.     double D_2 = FindOutFaceD(vector_normal_2.x, vector_normal_2.y, vector_normal_2.z, triangles_points[0]);
  235.  
  236.     Point other_point = GetOtherPoint(triangles_points, points); // проверяем только на одной точке
  237.  
  238.     if (vector_normal_1*other_point + D_1 < 0) { //приколюшка только для грани!!!
  239.         return vector_normal_1;
  240.     }
  241.     else if (vector_normal_2*other_point + D_2 < 0) {
  242.         return vector_normal_2;
  243.     }
  244.     else {
  245.         std::cout<<"Can't Find External Vector for Triangle";
  246.         exit(1);
  247.     }
  248. }
  249.  
  250.  
  251.  
  252. std::vector<Point> Triangle::GetPointsInProperOrder(const std::vector<Point> &points) {
  253.     Triangle this_triangle = *this;
  254.     std::vector<Point> triangle_points = GetPointsOfTriangle(this_triangle);
  255.  
  256.     if (triangle_points.size() < 3) {
  257.         std::cerr<<" triangles_points.size() < 3 ";
  258.         exit(1);
  259.     }
  260.  
  261.     std::vector<Point> proper_order_points;
  262.     Point external_normal_vector = this->GetExternalVector(points);
  263.     int iter_of_min = 0;                                                                            //FIX!!!
  264.     for (int i = 1; i < triangle_points.size(); ++i) {
  265.         if (triangle_points[iter_of_min].number > triangle_points[i].number) {
  266.             iter_of_min = i;
  267.         }
  268.     }
  269.     std::swap(triangle_points[iter_of_min],triangle_points[0]);
  270.     proper_order_points.push_back(triangle_points[0]);
  271.  
  272.     Point v1 = VectorMultiplication(triangle_points[1] - triangle_points[0],external_normal_vector);
  273.     Point v2 = VectorMultiplication(triangle_points[2] - triangle_points[0],external_normal_vector);
  274.     double D_1 = FindOutFaceD(v1.x , v1.y, v1.z, triangle_points[1]);
  275.     double D_2 = FindOutFaceD(v2.x , v2.y, v2.z, triangle_points[2]);
  276.     if ( v1*triangle_points[2] + D_1 < 0 ) {
  277.         proper_order_points.push_back(triangle_points[1]);
  278.         proper_order_points.push_back(triangle_points[2]);
  279.     }
  280.     else if ( v2*triangle_points[1] + D_2 < 0 ) {
  281.         proper_order_points.push_back(triangle_points[2]);
  282.         proper_order_points.push_back(triangle_points[1]);
  283.     }
  284.     else {
  285.         std::cout<<"Can't find right order";
  286.         exit(1);
  287.     }
  288.     return proper_order_points;
  289. }
  290.  
  291.  
  292. std::vector<Edge> Triangle::GetEdges() {
  293.     return {edge12,edge23,edge31};
  294. }
  295.  
  296.  
  297. bool IsFace(Triangle& triangle, const std::vector<Point>& points) { // how to do O(1)
  298.     std::vector<Point> triangles_points = GetPointsOfTriangle(triangle);
  299.     Point normal = triangle.GetExternalVector(points);
  300.  
  301.     double D_of_triangle = FindOutFaceD(normal.x, normal.y, normal.z, triangles_points[0]);
  302.     std::vector<double> D_of_other_points;
  303.     for (const auto& point: points) {
  304.         if ( (point !=  triangles_points[1] && point !=  triangles_points[2]) && point !=  triangles_points[0]) {
  305.             double D = FindOutFaceD(normal.x, normal.y, normal.z, point);
  306.             D_of_other_points.push_back(D);
  307.         }
  308.     }
  309.     double min_element = *std::min_element(D_of_other_points.begin(), D_of_other_points.end());
  310.     double max_element = *std::max_element(D_of_other_points.begin(), D_of_other_points.end());
  311.     bool result = (D_of_triangle < min_element ||
  312.             D_of_triangle > max_element ) ;
  313.     return result;
  314. }
  315.  
  316.  
  317. Edge FindEdgeOnHull(const std::vector<Point>& points) {
  318.     Point p1 = MostBottom(points);
  319.     Point p2 = OtherPointFromSet(p1, points);
  320.     for (const auto& point: points) {
  321.         if ( p1 != point && OzAngle(p1,point) >= OzAngle(p1,p2) ) {
  322.             p2 = point;
  323.         }
  324.     }
  325.     return {p1,p2,p1};
  326. }
  327.  
  328.  
  329. Triangle FindtTriangleOnHull(std::vector<Point>& points) { //O(n^2)
  330.     Edge edge = FindEdgeOnHull(points);
  331.     Point pivot = edge.PivotAroundEdge(points);
  332.     edge.forbidden_point = pivot;
  333.     return  {edge, pivot};
  334. }
  335.  
  336.  
  337. Triangle FindNewTriangle(const std::vector<Point> &points, const Edge& edge) {
  338.  
  339.     Point p1 = edge.p1;
  340.     Point p2 = edge.p2;
  341.     Point p3 = edge.forbidden_point;
  342.     std::vector<Point> triangle_points = {p1,p2,p3};
  343.  
  344.     Point rotate_vector (0,0,0);
  345.     Point base_point (0,0,0);
  346.     Point normal (0,0,0);
  347.  
  348.     Point p1p2 = p2 - p1;
  349.     Point p2p1 = p1 - p2;
  350.     Point norm_v1 = VectorMultiplication(p1p2,p3-p1);
  351.     Point norm_v2 = VectorMultiplication(p2p1,p3-p2);
  352.     Point other_point = GetOtherPoint(triangle_points, points);
  353.     if (norm_v1*other_point + FindOutFaceD(norm_v1.x, norm_v1.y, norm_v1.z, p1) < 0) {
  354.         rotate_vector = p1p2;
  355.         base_point = p1;
  356.         normal = norm_v1;
  357.     }
  358.     else if (norm_v2*other_point + FindOutFaceD(norm_v2.x, norm_v2.y, norm_v2.z, p1) < 0) {
  359.         rotate_vector = p2p1;
  360.         base_point = p2;
  361.         normal = norm_v2;
  362.     }
  363.     else {
  364.         std::cerr<<" Can't find rotate vector for ";
  365.         edge.p1.Print();
  366.         edge.p2.Print();
  367.         exit(1);
  368.     }
  369.  
  370.     Point pivot = other_point;
  371.     Point current_vector = VectorMultiplication(pivot - base_point, rotate_vector);
  372.  
  373.     for (const auto& point: points) { // need O(n)
  374.         if ((point != p1 && point != p2) && point != p3) {
  375.  
  376.             Point newvector = VectorMultiplication(point - base_point, rotate_vector);
  377.             double newcos = (newvector * normal)/(newvector.GetModule() * normal.GetModule());
  378.             double currentcos = (current_vector * normal)/(current_vector.GetModule() * normal.GetModule());
  379.  
  380.             if ( newcos > currentcos ) { // O(1)
  381.                 pivot = point;
  382.             }
  383.         }
  384.     }
  385.     return {edge, pivot};
  386. }
  387.  
  388.  
  389. Point Edge::PivotAroundEdge(const std::vector<Point> &points) { // O(n^2)
  390.     Point p1 = this->p1;
  391.     Point p2 = this->p2;
  392.     for (const auto& point: points) {
  393.         if ((point != p1 && point != p2)) {
  394.             Edge this_edge = *this;
  395.             Triangle triangle (this_edge, point);
  396.             if (IsFace(triangle, points)) { // O(n)
  397.                 return point;
  398.             }
  399.         }
  400.     }
  401. }
  402.  
  403.  
  404. bool IsNotUsedEdges(const std::vector<Edge>& edges) {
  405.     bool result = true;
  406.     for (auto edge: edges) {
  407.         result = result && edge.IsProcessed;
  408.     }
  409.     return  !result;
  410. }
  411.  
  412. template <class T>
  413. bool IsIn(const T& myelement, std::vector<T>& elements) {
  414.     for (int i = 0; i < elements.size(); ++i) {
  415.         if (myelement == elements[i]) {
  416.             elements[i].IsProcessed = true;
  417.             return true;
  418.         }
  419.     }
  420.     return  false;
  421. }
  422.  
  423.  
  424. void GiftWrapping(std::vector<Point>& points, std::vector<Triangle> & faces) {
  425.     Triangle t = FindtTriangleOnHull(points); // O(n^2)
  426.     faces.push_back(t);
  427.     std::vector<Edge> edges = t.GetEdges();
  428.     while (true) {
  429.         Edge newedge = edges[0];
  430.         bool flag = false;
  431.         for (auto& edge: edges) {
  432.             if (!edge.IsProcessed) {
  433.                 flag = true;
  434.                 edge.IsProcessed = true;
  435.                 newedge = edge;
  436.                 break;
  437.             }
  438.         }
  439.         if (flag) {
  440.             Triangle newtriangle = FindNewTriangle(points, newedge); //O(n)
  441.             std::vector<Edge> triangles_edges = newtriangle.GetEdges();
  442.             for (const auto& edge: triangles_edges) {
  443.                 if (!IsIn(edge, edges)) {                       //O(n)
  444.                     edges.insert(edges.begin(), edge);
  445.                 }
  446.             }
  447.             faces.push_back(newtriangle);
  448.         } else {
  449.             break;
  450.         }
  451.     }
  452. }
  453.  
  454.  
  455. void SortByDigit(std::vector<std::vector<int>>& vector, int digit_number) {
  456.     std::sort(vector.begin(), vector.end(),
  457.               [digit_number](const std::vector<int>& a, const std::vector<int>&b) {
  458.                   return a[digit_number] < b[digit_number];
  459.               });
  460. }
  461.  
  462.  
  463. void Start() {
  464.  
  465.     std::vector<std::vector<std::vector<int>>> result;
  466.     int m; // число тестов
  467.     std::cin>>m;
  468.  
  469.     for (int i = 0; i < m; ++i) {
  470.         int n; // число точек
  471.         std::cin>>n;
  472.         std::vector<Point> points;
  473.         std::vector<Triangle> faces;
  474.         for (int j = 0; j < n; ++j) {
  475.             int x,y,z;
  476.             std::cin>>x>>y>>z;
  477.             points.emplace_back(Point(x,y,z,j));
  478.         }
  479.  
  480.         GiftWrapping(points, faces);
  481.  
  482. //      std::cout<<faces.size()<<std::endl;
  483.  
  484.         std::vector<std::vector<int>> lexic_order(faces.size());
  485.         for (int k = 0; k < faces.size(); ++k) {
  486.             lexic_order[k].push_back(3);
  487.             for (auto point: faces[k].GetPointsInProperOrder(points)) {
  488.                 lexic_order[k].push_back(point.number);
  489.             }
  490.         }
  491.         // sort
  492.         for (int t = lexic_order[0].size() - 1; t > 0 ; --t) {
  493.             SortByDigit(lexic_order, t);
  494.         }
  495.  
  496.         result.push_back(lexic_order);
  497.  
  498.         // output
  499.     }
  500.  
  501.     for (int l = 0; l < m; ++l) {
  502.         std::cout<<result[l].size()<<std::endl;
  503.  
  504.         int fase_number = result[l].size();
  505.         for (const auto& face: result[l]) {
  506.             for (const auto& number: face) {
  507.                 std::cout<<number<<' ';
  508.             }
  509.             --fase_number;
  510.             std::cout<<'\n';
  511.  
  512.         }
  513.         if (fase_number != 0) {
  514.             std::cout << '\n';
  515.         }
  516.     }
  517. }
  518.  
  519.  
  520. bool predicate(const Point& p1, const Point& p2) {
  521.     return (p1 == p2);
  522. }
  523.  
  524. int main() {
  525.  
  526.     Start();
  527.  
  528.     return  0;
  529. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement