Existem N pontos no espaço 3D que compõem um casco 3D convexo *. Quantas faces possui o casco 3D convexo? É garantido que todos os pontos não estão no mesmo plano.
Caso você não saiba a definição de casco convexo, apresentamos aqui um esclarecimento da Wikipedia:
* Casco convexo: Em matemática, o casco convexo, para um conjunto de pontos X em um espaço vetorial real V, é o mínimo convexo conjunto contendo X.
Caso você não saiba a definição de casco convexo, apresentamos aqui um esclarecimento da Wikipedia:
* Casco convexo: Em matemática, o casco convexo, para um conjunto de pontos X em um espaço vetorial real V, é o mínimo convexo conjunto contendo X.
InputThere são vários casos de teste. Em cada caso, a primeira linha contém um número inteiro N indica o número de pontos 3D (3 <N <= 300) e, em seguida, N linhas seguem, cada linha contém três números x, y, z (entre -10000 e 10000) indicam a posição 3d de um ponto. SaídaUtilize o número de faces do casco 3D-convexo.
Entrada de amostra
7 1 1 0 1 -1 0 -1 1 0 -1 -1 0 0 0 1 0 0 0 0 0 -0.1 7 1 1 0 1 -1 0 -1 1 0 -1 -1 0 0 0 1 0 0 0 0 0 0,1
Saída de amostra
8 5
#include <cmath> #include <cstdio> #include <cstring> #include <algorithm> usando o namespace std; const int N = 303 ; const duplo eps = 1-6 ; ponto de estrutura { double x, y, z; Ponto ( double _x = 0 , double _y = 0 , double _z = 0 ): x (_x), y (_y), z (_z) {} Operador de ponto + ( const Point & A) const{ Ponto de retorno (x + Ax, y + Ay, z + Az); } Operador de ponto - ( const Point & A) const { retornar ponto (x - Ax, y - Ay, z - Az); } operador duplo * ( const Point & A) const { retorno x * Ax + y * Ay + z * Az; } Operador de ponto ^ ( const Point & A) const { retornar ponto (y * Az - z * Ay, z * Ax - x * Az, x * Ay - y * Ax); } sqrlen duplo () { retorno x * x + y * y + z * z; } } P [N]; struct Face { int a, b, c; bool ex; Face ( int _a = 0 , int _b = 0 , int _c = 0 , bool _ex = false ): a (_a), b (_b), c (_c), ex (_ex) {} } F [N * N ]; int n, ftot, LeftFace [N] [N]; void insFace ( int a, int b, int c, int n1, int n2, int n3) { F [ ++ ftot] = (Face) {a, b, c, verdadeiro }; LeftFace [a] [b] = LeftFace [b] [c] = LeftFace [c] [a] = ftot; Lado esquerdo [b] [a] = n1; Face esquerda [c] [b] = n2; Face esquerda [a] [c] = n3; } bool visível ( int f, int p) { Ponto a = P [F [f] .b] - P [F [f] .a], b = P [F [f] .c] - P [F [ f] .a]; retorno (P [p] - P [F [f] .a]) * (a ^ b)> eps; } intst, para [N], ps [N], pt [N], ptot =0 , pf [N]; void dfs ( int x, int s, int t, int p) { if (F [x] .ex == false ) return ; if (visível (x, p)) F [x] .ex = false ; senão { to [st = s] = t; retorno ; } dfs (Face esquerda [F [x] .b] [F [x] .a], F [x] .a, F [x] .b, p); dfs (Lado Esquerdo [F [x]. c] [F [x]. b], F [x]. b, F [x]. c, p); dfs (Face esquerda [F [x] .a] [F [x] .c], F [x] .c, F [x] .a, p); } Ponto ff; vaziodfs2 ( int x) { if (F [x] .ex == false ) return ; Aponte agora = (P [F [x] .b] - P [F [x] .a]) ^ (P [F [x] .c] - P [F [x] .a]); if (fabs (agora * ff - sqrt (now.sqrlen () * ff.sqrlen ())) < 1-6 ) F [x] .ex = false ; mais retornar ; dfs2 (Lado esquerdo [F [x] .b] [F [x] .a]); dfs2 (Lado Esquerdo [F [x] .c] [F [x] .b]); dfs2 (Lado Esquerdo [F [x] .a] [F [x] .c]); } int main () { while (~ scanf ( " % d " , &n)) { ;para ( int i = 1 ; i <= n; ++ i) scanf ( " % lf% lf% lf " , & P [i] .x, & P [i] .y, & P [i] .z); ftot = 0 ; Ponto a, b, c, d, e; a = P [ 2 ] - P [ 1 ]; int tmp, id1, id2; para (tmp = 3 ; tmp <= n; ++ tmp) { b = P [tmp] - P [ 1 ]; d = a ^ b; se (d.sqrlen () <eps) continuar id1= tmp; quebrar ; } para (++ tmp; tmp <= n; ++ tmp) { c = P [tmp] - P [ 1 ]; se (fabs (d * c) <eps) continuar ; id2 = tmp; quebrar ; } if (d * c < 0 ) swap (id1, id2); insFace ( 1 , 2 , id2, 3 , 4 , 2 ); insFace ( 1 , id2, id1, 1 , 4 , 3 ); insFace ( 1 , id1, 2 , 2 , 4 , 1 ); insFace ( 2 , id1, id2, 3 , 2 , 1 ); para ( int i = 3 ; i <= n; ++ i) { se (i == id1 || i == id2) continue ; for ( int j = 1 ; j <= ftot; ++ j) if (F [j] .ex && visible (j, i)) { dfs (j, 0, 0 , i); ptot = 0 ; int tmps = st, tmpt = para [st], ppff = ftot; faça { ++ ptot; ps [ptot] = tmps; pt [ptot] = tmpt; pf [ptot] = ++ ppff; tmps = tmpt; tmpt = para [tmpt]; } while (tmps! = st); for ( int k = 1 , pre, suc; k <= ptot; ++ k) { pre = k - 1 ; suc = k + 1 ; if (pre == 0 ) pre = ptot; if (suc> ptot) suc = 1 ; pre = pf [pré]; suc = pf [suc]; insFace (pt [k], i, ps [k], suc, pre, LeftFace [pt [k]] [ps [k]]); } quebrar ; } } int ans = 0 ; for ( int i = 1 ; i <= ftot; ++ i) se (F [i] .ex) { ++ ans; ff = (P [F [i] .b] - P [F [i] .a]) ^ (P [F [i] .c] - P [F [i] .a]); dfs2 (i); } printf ( " % d \ n " , ans); } retornar 0 ; }