Submission #35198


Source Code Expand

#include<cmath>
#include<algorithm>
#include"ghost.h"
#include"grader.h"

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

const double EPS=1e-11;

template<class T>
struct point{
	T x,y,z;
	point operator+(const point &a)const{ return (point){x+a.x,y+a.y}; }
	point operator-(const point &a)const{ return (point){x-a.x,y-a.y}; }
};

template<class T>
point<T> operator*(T c,const point<T> &a){ return (point<T>){c*a.x,c*a.y}; }

bool cmp_yz(const point<double> &a,const point<double> &b){
	return a.y+EPS<b.y || abs(a.y-b.y)<EPS && a.z+EPS<b.z;
}

template<class T>
T cross(const point<T> &a,const point<T> &b){ return a.x*b.y-a.y*b.x; }

template<class T>
struct line{ point<T> a,b; };

template<class T>
point<double> get_intersect(const line<T> &L1,const line<T> &L2){
	double a1=cross(L1.b-L1.a,L2.b-L2.a);
	double a2=cross(L1.b-L1.a,L1.b-L2.a);
	if(a1==0) return L1.a; // L1 == L2
	return (point<double>)L2.a+a2/a1*(point<double>)(L2.b-L2.a);
}

double dist_xz(const point<double> &a,const point<double> &b){
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.z-b.z)*(a.z-b.z));
}

double f(int n,const point<double> *C,const point<double> *T,const point<double> &G){
	double dif=0;
	rep(i,n){
		dif+=abs(T[i].z-(C[i].z+dist_xz(C[i],T[i])/dist_xz(C[i],G)*(G.z-C[i].z)));
	}
	return dif;
}

void FindGhost(int n,double Cx[],double Cy[],double Cz[],double Ty[],double Tz[]){
	// まず z=0 の平面で考える
	static point<double> C[100000],T[100000]; // candle, target
	rep(i,n){
		C[i]=(point<double>){Cx[i],Cy[i],Cz[i]};
		T[i]=(point<double>){0,Ty[i],Tz[i]};
	}

	sort(T,T+n,cmp_yz);

	const line<double> L={(point<double>){1,0},(point<double>){1,1}}; // 直線 x=1
	double y_min=77,y_max=-77;
	rep(i,n){
		y_min=min(y_min,get_intersect((line<double>){C[i],T[n-1]},L).y);
		y_max=max(y_max,get_intersect((line<double>){C[i],T[ 0 ]},L).y);
	}

	// 平面 z=0 に射影したおばけの位置
	point<double> G=get_intersect((line<double>){(point<double>){1,y_min},T[n-1]},
								  (line<double>){(point<double>){1,y_max},T[ 0 ]});

	// ろうそくたちを <ろうそくとおばけを結ぶ線分と直線 x=1 の交点の y 座標, ろうそくの z 座標> の辞書順でソート
	static pair<pair<double,double>,int> Y[100000];
	rep(i,n){
		Y[i]=make_pair(make_pair(get_intersect((line<double>){C[i],G},L).y,C[i].z),i);
	}
	sort(Y,Y+n);
	static point<double> tmp[100000];
	rep(i,n) tmp[i]=C[i];
	rep(i,n) C[i]=tmp[Y[n-i-1].second];

	// おばけの z 座標を三分探索で求める
	double lo=0,hi=1;
	rep(_,40){
		double mi1=(2*lo+hi)/3,mi2=(lo+2*hi)/3,f1,f2;
		G.z=mi1; f1=f(n,C,T,G);
		G.z=mi2; f2=f(n,C,T,G);
		if(f1<f2) hi=mi2; else lo=mi1;
	}
	answer(G.x,G.y,G.z);
}

Submission Info

Submission Time
Task B - やさしいおばけ の たんじょうびかい (Friendly Ghost's Birthday Party)
User fura2
Language IOI-Style C++ (GCC 5.4.1)
Score 100
Code Size 2789 Byte
Status AC
Exec Time 706 ms
Memory 14080 KB

Judge Result

Set Name Subtask1 Subtask2 Subtask3
Score / Max Score 19 / 19 40 / 40 41 / 41
Status
AC × 8
AC × 8
AC × 16
Set Name Test Cases
Subtask1 subtask1/1, subtask1/2, subtask1/3, subtask1/4, subtask1/5, subtask1/6, subtask1/7, subtask1/8
Subtask2 subtask2/1, subtask2/2, subtask2/3, subtask2/4, subtask2/5, subtask2/6, subtask2/7, subtask2/8
Subtask3 subtask1/1, subtask1/2, subtask1/3, subtask1/4, subtask1/5, subtask1/6, subtask1/7, subtask1/8, subtask3/1, subtask3/2, subtask3/3, subtask3/4, subtask3/5, subtask3/6, subtask3/7, subtask3/8
Case Name Status Exec Time Memory
subtask1/1 AC 25 ms 3084 KB
subtask1/2 AC 27 ms 3072 KB
subtask1/3 AC 25 ms 3068 KB
subtask1/4 AC 25 ms 3064 KB
subtask1/5 AC 24 ms 3092 KB
subtask1/6 AC 24 ms 3088 KB
subtask1/7 AC 25 ms 3072 KB
subtask1/8 AC 25 ms 3064 KB
subtask2/1 AC 681 ms 14012 KB
subtask2/2 AC 662 ms 14020 KB
subtask2/3 AC 674 ms 14024 KB
subtask2/4 AC 669 ms 14024 KB
subtask2/5 AC 664 ms 13924 KB
subtask2/6 AC 670 ms 14028 KB
subtask2/7 AC 642 ms 13816 KB
subtask2/8 AC 647 ms 13820 KB
subtask3/1 AC 702 ms 13964 KB
subtask3/2 AC 699 ms 14028 KB
subtask3/3 AC 706 ms 14024 KB
subtask3/4 AC 704 ms 14080 KB
subtask3/5 AC 701 ms 14072 KB
subtask3/6 AC 699 ms 14028 KB
subtask3/7 AC 688 ms 13816 KB
subtask3/8 AC 684 ms 13824 KB