問題はこちら
No.132 点と平面との距離 - yukicoder
点と直線の距離の公式は有名で、直線ax+by+c=0と点(p,q)の距離はで与えられる
これと同様に、平面ax+by+cz+d=0と点(p,q,r)の距離はで点と平面の距離の公式が与えられる
また、2点(xi,yi,zi)が与えられた時、その2点と原点を通る平面をax+by+cz=0とすると(x1,y1,z1)×(x2,y2,z2)=(a,b,c)となる(×はベクトル外積)
((a,b,c)が平面ax+by+cz=0の法線ベクトルであることを考えれば外積の定義から明らか)
以上を用いて求めることができる
int main(){ double x[301],y[301],z[301],p,q,r,s; int n,i,j,k; scanf("%d",&n); for(i=0;i<n;i++)scanf("%lf%lf%lf",x+i,y+i,z+i); for(i=0;++i<n;)for(j=i;++j<n;)for(k=j;++k<n;){ p=(y[j]-y[i])*(z[k]-z[i])-(z[j]-z[i])*(y[k]-y[i]); q=(z[j]-z[i])*(x[k]-x[i])-(x[j]-x[i])*(z[k]-z[i]); r=(x[j]-x[i])*(y[k]-y[i])-(y[j]-y[i])*(x[k]-x[i]); //(x[i],y[i],z[i])が原点になるように平行移動しつつ外積を求める s+=fabs(p*(x[0]-x[i])+q*(y[0]-y[i])+r*(z[0]-z[i]))/sqrt(p*p+q*q+r*r); } printf("%f",s); return 0; }
for(i=0;++i<n;)for(j=i;++j<n;)for(k=j;++k<n;)
はループを逆にして
for(i=n;--i;)for(j=i;--j;)for(k=j;--k;)
これを変数の初期化に気をつけながら圧縮し、さらにループの中身をdefineでまとめる
#define f(x,y)(x[j]-x[k])*(y[i]-y[k])-(y[j]-y[k])*(x[i]-x[k]), double x[301],y[301],z[301],p,q,r,s; i,k; main(j){ for(gets(&p);~scanf("%lf%lf%lf",x+i,y+i,z+i)?++i:k?k--,p=f(y,z)q=f(z,x)r=f(x,y)s+=fabs(p*(*x-x[k])+q*(*y-y[k])+r*(*z-z[k]))/sqrt(p*p+q*q+r*r):(k=--j)?:(j=--i);); k=!printf("%f",s); }
流石にもっと短くなりそうだけど思いつかない
291B