Advertisement
blufzzz

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

Nov 25th, 2017
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.17 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.  
  351. Point Edge::PivotAroundEdge(const std::vector<Point> &points) { // O(n^2)
  352. Point p1 = this->p1;
  353. Point p2 = this->p2;
  354. for (const auto& point: points) {
  355. if ((point != p1 && point != p2)) {
  356. Edge this_edge = *this;
  357. Triangle triangle (this_edge, point);
  358. if (IsFace(triangle, points)) { // O(n)
  359. return point;
  360. }
  361. }
  362. }
  363. }
  364.  
  365.  
  366. bool IsNotUsedEdges(const std::vector<Edge>& edges) {
  367. bool result = true;
  368. for (auto edge: edges) {
  369. result = result && edge.IsProcessed;
  370. }
  371. return !result;
  372. }
  373.  
  374. template <class T>
  375. bool IsIn(const T& myelement, std::vector<T>& elements) {
  376. for (int i = 0; i < elements.size(); ++i) {
  377. if (myelement == elements[i]) {
  378. elements[i].IsProcessed = true;
  379. return true;
  380. }
  381. }
  382. return false;
  383. }
  384.  
  385.  
  386. void GiftWrapping(std::vector<Point>& points, std::vector<Triangle> & faces) {
  387. Triangle t = FindtTriangleOnHull(points); // O(n^2)
  388. faces.push_back(t);
  389. std::vector<Edge> edges = t.GetEdges();
  390. while (IsNotUsedEdges(edges)) { // O(n)
  391. Edge &newedge = edges.back();
  392. if (!newedge.IsProcessed) {
  393. newedge.IsProcessed = true;
  394. Triangle newtriangle = FindNewTriangle(points, newedge); //O(n) //
  395. std::vector<Edge> triangles_edges = newtriangle.GetEdges();
  396. for (const auto& edge: triangles_edges) {
  397. if (!IsIn(edge, edges)) {
  398. edges.push_back(edge);
  399. }
  400. }
  401. faces.push_back(newtriangle);
  402. }
  403.  
  404. }
  405. }
  406.  
  407.  
  408. void SortByDigit(std::vector<std::vector<int>>& vector, int digit_number) {
  409. std::sort(vector.begin(), vector.end(),
  410. [digit_number](const std::vector<int>& a, const std::vector<int>&b) {
  411. return a[digit_number] < b[digit_number];
  412. });
  413. }
  414.  
  415.  
  416. void Start() {
  417.  
  418. int m; // число тестов
  419. std::cin>>m;
  420.  
  421. for (int i = 0; i < m; ++i) {
  422. int n; // число точек
  423. std::cin>>n;
  424. std::vector<Point> points;
  425. std::vector<Triangle> faces;
  426. for (int j = 0; j < n; ++j) {
  427. int x,y,z;
  428. std::cin>>x>>y>>z;
  429. points.emplace_back(Point(x,y,z,j));
  430. }
  431.  
  432. GiftWrapping(points, faces);
  433.  
  434. std::cout<<faces.size()<<std::endl;
  435.  
  436. std::vector<std::vector<int>> lexic_order(faces.size());
  437. for (int k = 0; k < faces.size(); ++k) {
  438. lexic_order[k].push_back(3);
  439. for (auto point: faces[k].GetPointsInProperOrder(points)) {
  440. lexic_order[k].push_back(point.number);
  441. }
  442. }
  443. // sort
  444. for (int t = lexic_order[0].size() - 1; t > 0 ; --t) {
  445. SortByDigit(lexic_order, t);
  446. }
  447. // output
  448. for (const auto& face: lexic_order) {
  449. for (const auto& number: face) {
  450. std::cout<<number<<' ';
  451. }
  452. std::cout<<'\n';
  453. }
  454. }
  455. }
  456.  
  457.  
  458. bool predicate(const Point& p1, const Point& p2) {
  459. return (p1 == p2);
  460. }
  461.  
  462. int main() {
  463.  
  464. // Point p1 (0,0,0,0);
  465. // Point p2 (10,0,0,1);
  466. // Point p3 (0,10,0,2);
  467. // Point p4 (10,10,10,3);
  468. // Point p5 (5,5,10,4);
  469. //
  470. // std::vector<Point> points = {p1,p2,p3,p4,p5};
  471. //
  472. // std::vector<Triangle> faces;
  473. // GiftWrapping(points, faces);
  474.  
  475. Start();
  476.  
  477. return 0;
  478. }
  479.  
  480. // std::sort(points.begin(), points.end(), [](const Point& p1, const Point& p2){ return p1.number <= p2.number ; });
  481. // auto last = std::unique(points.begin(), points.end());
  482. // points.erase(last, points.end());
  483. //
  484. // for (auto point : points) {
  485. // point.Print();
  486. // }
  487. //
  488. // std::cout<<'\n';
  489. //
  490. // Edge edge(p1,p3,p5);
  491. // Triangle triangle(edge, p5);
  492. // std::vector<Point> point_tr = GetPointsOfTriangle(triangle);
  493. // for (auto point : point_tr) {
  494. // point.Print();
  495. // }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement