Advertisement
Tucancitto

Proiect AF - Secționare hârtie (Gaură cub)

Jan 2nd, 2021 (edited)
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.84 KB | None | 0 0
  1. /*
  2. https://codingcompetitions.withgoogle.com/codejam/round/00000000000000cb/00000000000079cc#problem
  3. PROBLEMĂ
  4.  
  5. Un cub este lăsat să cadă printr-o hârtie subțire. Hârtia reprezintă un plan într-un spațiu tridimensional, are coordonata Y = -10 m
  6. și este paralelă cu axele X și Z. Cubul își are centrul în punctul (0, 0, 0), laturile sale au lungimea de 1 m, iar colțurile sale
  7. au coordonatele (+/- 0.5, +/- 0.5, +/- 0.5). În căderea sa, cubul nu se rotește, iar traiectoria căderii sale este perpendiculară
  8. pe planul X Z. La impact, cubul trece prin hârtie și lasă în urma sa o gaură ce ia forma proiecției cubului pe planul
  9. hârtiei. Găsiți un mod de a roti cubul așa încât să lase pe hârtie o gaură de arie A m^2. Exprimați rotația folosind trei puncte
  10. din spațiu: centrele a trei fețe ale cubului ce formează un colț.
  11. */
  12.  
  13. #include <iostream>
  14. #include <cmath>
  15. #include <iomanip>
  16. using namespace std;
  17.  
  18. void ProdusMatrice3x3(double matA[3][3], double matB[3][3], double rezultat[3][3]) // Calculeaza produsul matricilor matA si matB.
  19. {                                                                                  // Produsul este memorat in matricea rezultat.
  20.     for (int i = 0; i < 3; i++)
  21.         for (int j = 0; j < 3; j++)
  22.             rezultat[i][j] = matA[i][0] * matB[0][j] + matA[i][1] * matB[1][j] + matA[i][2] * matB[2][j];
  23. }
  24.  
  25. void rezolvare(double A, double solutie[3][3])
  26. {
  27.     const double sqrt2 = sqrt(double(2));
  28.     const double sqrtHalf = sqrt(double(0.5));
  29.     // Constantele sqrt2 si sqrtHalf au fost initializate pentru usurarea calculelor de mai jos.
  30.  
  31.     double rotate45[3][3]
  32.     {
  33.         sqrtHalf, 0, sqrtHalf,
  34.         0, 1, 0,
  35.         -sqrtHalf, 0, sqrtHalf
  36.     };
  37.  
  38.     // Pentru a roti cubul tridimensional vom folosi matrice de rotatie.
  39.     // Matricea rotate45 este utilizata pentru a roti cubul cu 45 de grade pe axa Y.
  40.     // rotate45 are ca scop usurarea determinarii unei proiectii a cubului ce are aria (aproape) A.
  41.  
  42.     // Fiind o problema care cere doar o solutie posibila, aceasta poate fi rezolvata in mai multe moduri. Pot fi mai mutle output-uri
  43.     // corecte pentru acelasi input.
  44.  
  45.     // Metoda propusa este urmatoarea: Cubul este initial rotit cu 45 de grade pe axa Y. Rotirile subsecvente vor avea loc pe axa Z,
  46.     // in urma carora proiectia cubului pe plan va avea forma unui hexagon. Hexagonul va fi alcatuit din 2 triunghiuri isoscele egale
  47.     // si un dreptunghi (in cazul in care proiectia cubului este un patrat, va fi considerat ca fiind un hexagon cu latimea dreptunghiului
  48.     // egala cu 0 m; daca este un dreptunghi, va fi considerat ca fiind un hexagon cu inaltimile triunghiurilor egale cu 0 m). Triunghiurile
  49.     // pot fi rearanjate asa incat hexagonul devine un dreptunghi (*). Se determina matematic ca dreptunghiul rezultat are lungimea egala cu sqrt(2)
  50.     // si latimea egala cu sqrt(2)/2*cos(Alfa)+sin(Alfa), unde Alfa este unghiul de rotatie pe axa Z. Stiind ca aria dreptunghiului este A,
  51.     // putem determina sin(Alfa) si cos(Alfa), cu ajutorul carora aflam matricea de rotatie pe axa Z.
  52.  
  53.     const double sqrtDelta = sqrt(3 - A * A); // Se ajunge la o ecuatie de gradul 2 unde x = sin(Alfa). Prin calcul se ajunge la Delta = 3 - A^2.
  54.     const double cosAlfa = (A + sqrtDelta * sqrt2) / 3;
  55.     const double sinAlfa = (A * sqrt2 - sqrtDelta) / 3;
  56.     double rezultat[3][3] = { cosAlfa, sinAlfa, 0, -sinAlfa, cosAlfa, 0, 0, 0, 1 }; // rezultat este matricea de rotatie pe axa Z pentru unghiul Alfa.
  57.  
  58.     ProdusMatrice3x3(rotate45, rezultat, solutie); // Solutia consta in produsul matricelor rotate45 si rezultat.
  59.     for (int i = 0; i < 3; i++)
  60.         for (int j = 0; j < 3; j++)
  61.             solutie[i][j] /= 2;
  62.  
  63.     // Elementele matricei solutie se impart la 2 deoarece matricea initiala a cubului este egala cu 0.5 * matricea unitate.
  64.     // ( Deoarece pozitia initiala a centrului cubului este (0,0,0), iar centrele a trei fete ale cubului ce formeaza un colt sunt
  65.     // (0.5, 0, 0), (0, 0.5, 0) si (0, 0, 0.5) ).
  66. }
  67.  
  68. int main()
  69. {
  70.     double A, C[3][3];
  71.     cout << "A = ";
  72.     cin >> A; // A = aria gaurii formate
  73.  
  74.     if (A >= 1 && A <= sqrt(3)) // 1 <= A <= 1.732050
  75.     {
  76.         rezolvare(A, C);
  77.         for (int i = 0; i < 3; i++) // Afisarea celor 3 puncte prin care se exprima rotatia cubului.
  78.         {
  79.             for (int j = 0; j < 3; j++)
  80.                 cout << setw(9) << C[i][j] << ' ';
  81.             cout << '\n';
  82.         }
  83.     }
  84.     else
  85.         cout << "Eroare: Aria nu poate avea valoarea data!";
  86.     return 0;
  87. }
  88.  
  89. // OBSERVATII:
  90. // - Coordonata Y a planului hartiei nu influenteaza solutia;
  91. // - Se observa faptul ca aria proiectiei cubului este minima cand are forma de patrat (A = 1) si maxima cand are forma de hexagon regulat (A = sqrt(3));
  92. // - Deoarece nu sunt utilizate structuri repetitive ce depind de valori date de la tastatura, algoritmul se rezolva in timp constant O(1).
  93. // - (*) Unul dintre cele doua triunghiuri va fi taiat in doua triunghiuri egale, care sunt atasate la celalalt triunghi pentru a forma un dreptunghi.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement