AOJのこちらの問題を綺麗に書こうと考えています。
Acceptedはもらえたのですが他に解き方は無いか教えてください(特に当たり判定)
ソースコード
► スポイラーを表示
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cassert>
#include <functional>
using namespace std;
class ufo{
public:
	int x;				//元のX座標
	int y;				//元のY座標
	int r;				//UFOの半径
	int v;				//UFOの速度
	int move_length;	//その時の合計移動距離
	int laser;			//レーザーの効かない範囲
	ufo( int x_,int y_,int r_, int v_, int laser_):
	x(x_),y(y_),r(r_),v(v_),move_length(v_),laser(laser_){}
	
	bool operator < (const ufo& one) const{
		return sqrt(x*x+y*y)-move_length < 
				sqrt(one.x*one.x + one.y*one.y) -one.move_length;
	}	//比較基準はその時の中心からの距離が近い順
	
	double length() const
	{
		return sqrt(x*x+y*y)-move_length;	//中心からの距離
	}
	
	double nowx() const//今のx座標
	{
		return x*(1-move_length/sqrt(x*x+y*y));
	}
	
	double nowy() const//今のY座標
	{
		return y*(1-move_length/sqrt(x*x+y*y));
	}
	
	bool move()//合計移動距離を分速分増やす
	{
		move_length += v;
		return move_length+laser >= sqrt(x*x+y*y);//通りすぎてないかのチェック
	}
};
bool hit(int laser,double x, double y,ufo one);
//当たり判定用関数
class can_shoot  : public std::binary_function<ufo, int, int>
{
public:
	bool operator() (ufo one,int laser) const
	{
		return one.length() > laser;
	}
	
};//UFOが射程圏内にいるかどうかのチェック
int main(){
	int laser,num;
	int answer = 0;
	int x,y,r,v;
	vector<ufo> vec;
	
	while(cin >> laser >> num){
		if(laser == 0 && num == 0)
			return 0;
		answer = 0;
//入力
		for(int i = 0 ; i < num; i++)
		{
		
			cin >> x >> y >> r >> v;
			vec.push_back(ufo(x,y,r,v,laser));
			
		}
//計算部分
		while(!vec.empty())
		{
			sort(vec.begin(),vec.end());		//中心から近い順にソート
			auto ite = find_if (vec.begin(), vec.end(), bind2nd(can_shoot(),laser) );
												//撃てるいちばん近い標的を探す
			for (auto i = vec.begin(); i!= ite; i++)
				answer++;						//撃てない機体分answerを増やす
			ite = vec.erase(vec.begin(),ite);	//撃てない機体をvectorから削除
			if(vec.empty()) break;				//この時点で空なら終了
			double now_x = vec[0].x;			//いちばん近いUFOの座標を記録
			double now_y = vec[0].y;			//この座標を狙ってレーザー発射
			vec.erase(vec.begin());				//いちばん近いUFOをvecから削除
			
			for(auto ite = vec.begin();ite != vec.end();)
			{
				if( hit(laser,now_x,now_y,*ite) )	//当たるなら
					ite = vec.erase(ite);			//削除
				else								//当たらないなら
					ite++;							//イテレーターを1つ進める
			}
			
			for(auto ite = vec.begin();ite != vec.end();)
			{
				if((*ite).move()){				//一分進めたときに原点を通り過ぎたら
					ite = vec.erase(ite);		//vecから削除してanswerを一増やす
					answer++;
				}else{							//当たらないなら
					ite++;						//イテレーターを1つ進める
				}
			}
			
			
		}
		cout << answer << endl;		//答えを表示
	}
	return 0;
}
bool hit(int laser,double x, double y,ufo one)
//引数は前から順に レーザーの効かない範囲 標的となっているUFOのx座標、y座標 当たるか判定をするUFO
{													//レーザーが効く点のうち一番原点に近い点をPとおく
	double laser_x = x*laser/sqrt(x*x+y*y);			//Pのx座標
	double laser_y = y*laser/sqrt(x*x+y*y);			//Pのy座標
	if( one.r										//UFOの半径が UFOの位置からPまでの距離より長ければ当たる
		>= sqrt( pow(laser_x-one.nowx() , 2.0)
				+pow(laser_y-one.nowy() , 2.0) ))
			return 1;
		
	if(y == one.nowy())						//標的UFOと判定UFOのy座標が同じなら
	{
		double kouten = //Pを通りレーザーに垂直な直線と標的UFOの中心と判定UFOの中心を結んだ直線の交点のx座標
		(y*( y*one.nowx()-x*one.nowy() ) + (x-one.nowx())*(x*laser_x+y*laser_y))
					/
				(y*y+x*x-y*one.nowy()-x*one.nowx());
		if((x <= kouten && kouten <= one.nowx()) || //交点が標的UFOと判定UFOの間にある
				(one.nowx() <= kouten && kouten <= x))
			return 0;								//当たらない
	}else{
		double kouten = //Pを通りレーザーに垂直な直線と標的UFOの中心と判定UFOの中心を結んだ直線の交点のy座標
		(x*( x*one.nowy()-y*one.nowx() ) + (y-one.nowy())*(x*laser_x+y*laser_y))
				/
			(x*x+y*y-x*one.nowx()-y*one.nowy());
		if((y <= kouten && kouten <= one.nowy()) || //交点が標的UFOと判定UFOの間にある
				(one.nowy() <= kouten && kouten <= y))
			return 0;								//当たらない
	}
	
	double result;
	result = (y*one.nowx()-x*one.nowy()) / sqrt(x*x+y*y);	//判定UFOの中心から直線レーザーにおろした垂線の長さ
	if(result < 0)
		result *= -1;				//絶対値が付いているので-なら+に補正
	
	return one.r >= result; 		//円の半径が垂線の長さより長ければ当たる
}
中央赤丸 :レーザー無効範囲
色つき円 :標的UFO
色なし緑円 :判定UFO
中央から延びる直線:レーザー 点線部は無効範囲 実線部は有効範囲
当たり判定は
①判定UFOからPまでの距離が半径より長ければtrue

②判定UFOから引いた垂線の足がレーザーの有効範囲にいるかのチェック
判定UFOの中心と標的UFOの中心を結んだ直線と
レーザーと赤円の交点を通り、レーザーに垂直な直線の交点(黄色丸)が
判定UFOと標的UFOの間にあればfalse

間に無ければ範囲内にいることだけは確定(true、falseはまだ判断つかない)

③判定UFOの中心からレーザーにおろした垂線の長さが半径より短ければtrue長ければfalse

としています。
正直マジックナンバーだらけで気持ち悪くって…
どうすればきれいに書けますか?
また、他にどんなとき方があるのか教えてください。