読者です 読者をやめる 読者になる 読者になる

メモ

yukicoderで遊んでいる競プロゆるふわ勢

yukicoder No.132 点と平面との距離

問題はこちら
No.132 点と平面との距離 - yukicoder

点と直線の距離の公式は有名で、直線ax+by+c=0と点(p,q)の距離は\displaystyle{\frac{|ap+bq+c|}{\sqrt{p^{2}+q^{2}}}}で与えられる
これと同様に、平面ax+by+cz+d=0と点(p,q,r)の距離は\displaystyle{\frac{|ap+bq+cr+d|}{\sqrt{p^{2}+q^{2}+r^{2}}}}で点と平面の距離の公式が与えられる
また、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