Problem:
問題 C : Apples

問題文

あるところに銃の腕に自信をもつ猟師がいました．
猟師はある日，「ウィリアムテルというスイス人が，息子の頭にりんごを乗せて遠くから矢で撃ち落とすパフォーマンスで有名になった」というお話を聞きました．
それを聞いて"自分のほうがもっと凄い!!"と思った猟師は動いている人の上にりんごを乗せて撃ちぬくパフォーマンスを考えつきました．

猟師は広場に N 人の人を集め，それぞれの人の上にりんごを乗せました．
i 番目の人は時刻 t=0 のとき，座標 (x_i,  y_i) にいます．
そこから単位時間あたり速度ベクトル (u_i,  v_i) にしたがって歩きます．
すなわち，時刻 t  ≥  0 のとき，i 番目の人は座標 (x_i + t \times u_i  ,   y_i + t \times v_i) にいます．
ここで，人々は十分小さいので，同じ座標に複数の人がいたり，同じ座標ですれ違ったりできると仮定します．

猟師は人々を驚嘆させるために，一発の弾丸でできるだけ多くのりんごを撃ち落とすことにしました．
猟師は t ≥ 0 であるような任意の時刻に，任意の座標から任意の方向に向けて弾丸を放つことができます．
放たれた弾丸は無限の速さで直線軌道で移動し，りんごに当たった場合貫通して移動します．
弾丸を一発だけ打つとき，最大で何個のりんごを撃ち落とせるか計算してください．

入力形式

入力は以下の形式で与えられる

N
x_0 y_0 u_0 v_0
...
x_{N-1} y_{N-1} u_{N-1} v_{N-1}

出力形式

撃ち落とせるりんごの最大個数を1行に出力せよ．

制約

1 ≤ N ≤ 200

0 ≤   |x_i|,   |y_i|   ≤ 10

0 ≤   |u_i|,   |v_i|   ≤ 3

入力値はすべて整数である。

入出力例

入力例 1

5
0 0 0 0
1 0 -1 1
-1 0 1 -1
1 1 -1 1
-1 -1 1 -1

出力例 1

5

時刻１に５人がｙ軸上に並ぶので最大５つのりんごを撃ち落とせる．

入力例 2

5
0 0 0 0
1 0 1 0
-1 0 -1 0
1 1 1 1
-1 -1 -1 -1

出力例 2

3

入力例 3

15
-10 9 2 1
2 10 0 -1
-10 -4 0 -3
-2 8 0 -1
0 -10 -1 -2
-8 5 0 -1
-7 -8 -3 1
10 -6 -2 -3
9 -6 1 0
10 -5 3 1
10 1 0 -3
-4 7 0 -1
10 -9 2 2
2 -5 -1 1
9 -10 3 1

出力例 3

5

Solution in Rust (judge verdict: Accepted)

extern crate core;

use std::fmt;
use std::cmp::{max, min, Ordering};
use std::collections::{BinaryHeap, BTreeMap, VecDeque};
use std::ops::{Range, Sub, Add};
use ::Suspects::All;
use std::fmt::{Display, Formatter, Error};
macro_rules! read_line{
    () => {{
        let mut line = String::new();
        std::io::stdin().read_line(&mut line).ok();
        line
    }};
    (delimiter: ' ') => {
        read_line!().split_whitespace().map(|x|x.to_string()).collect::<Vec<_>>()
    };
    (delimiter: $p:expr) => {
        read_line!().split($p).map(|x|x.to_string()).collect::<Vec<_>>()
    };
    (' ') => {
        read_line!(delimiter: ' ')
    };
    ($delimiter:expr) => {
        read_line!(delimiter: $delimiter)
    };
    (' '; $ty:ty) => {
        read_line!().split_whitespace().map(|x|x.parse::<$ty>().ok().unwrap()).collect::<Vec<$ty>>()
    };
    ($delimiter:expr; $ty:ty) => {
        read_line!($delimiter).into_iter().map(|x|x.parse::<$ty>().ok().unwrap()).collect::<Vec<$ty>>()
    };
}
macro_rules! let_all {
    ($($n:ident:$t:ty),*) => {
        let line = read_line!(delimiter: ' ');
        let mut iter = line.iter();
        $(let $n:$t = iter.next().unwrap().parse().ok().unwrap();)*
    };
}

fn main(){
    let_all!(n: usize);
    let mut persons = Vec::with_capacity(n);
    for _ in 0 .. n {
        let_all!(x: i32, y: i32, u: i32, v: i32);
        persons.push(Person{initial: Point{x: x, y: y}, velocity: Vector{dx: u, dy: v}});
    }
    println!("{}", solve(&persons));
}
#[derive(Copy, Clone, Eq, PartialEq)]
struct Point {
    x: i32, y: i32
}
#[derive(Copy, Clone, Eq, PartialEq)]
struct Vector {
    dx: i32, dy: i32
}
#[derive(Copy, Clone)]
struct PointF {
    x: f64, y: f64
}
impl Display for Point {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f, "Point(x: {}, y: {})", self.x, self.y)
    }
}
impl Display for Vector {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f, "Vector(dx: {}, dy: {})", self.dx, self.dy)
    }
}
impl Display for Person {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f, "Person(initial: {}, velocity: {})", self.initial, self.velocity)
    }
}
impl Display for PointF {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f, "Point(x: {}, y: {})", self.x, self.y)
    }
}
impl Vector {
    fn to_point(&self) -> Point {
        Point{x: self.dx, y: self.dy}
    }
}
#[derive(Copy, Clone, Eq, PartialEq)]
struct Person {
    initial: Point, velocity: Vector
}
impl Person {
    fn position_at(&self, time: f64) -> PointF {
        PointF{x: self.initial.x as f64 + self.velocity.dx as f64 * time, y: self.initial.y as f64 + self.velocity.dy as f64 * time}
    }

}
impl Sub for Point {
    type Output = Vector;
    fn sub(self, rhs: Point) -> Self::Output {
        Vector{dx: self.x - rhs.x, dy: self.y - rhs.y}
    }
}
impl Sub for Vector {
    type Output = Vector;
    fn sub(self, rhs: Vector) -> Self::Output {
        Vector{dx: self.dx - rhs.dx, dy: self.dy - rhs.dy}
    }
}
impl Sub for PointF {
    type Output = PointF;
    fn sub(self, rhs: PointF) -> Self::Output {
        PointF{x: self.x - rhs.x, y: self.y - rhs.y}
    }
}
enum Suspects<T> {
    All, Some{suspects: Vec<T>}, None
}
fn find_on_line_time(a: &Person, b: &Person, target: &Person) -> Suspects<f64> {
    let Vector{dx: a1, dy: c1} = a.initial - b.initial;
    let Vector{dx: b1, dy: d1}= a.velocity - b.velocity;
    let Vector{dx: a2, dy: c2} = target.initial - b.initial;
    let Vector{dx: b2, dy: d2} = target.velocity - b.velocity;
    let a = (b1 * d2 - d1 * b2) as f64;
    let b = (b1 * c2 + a1 * d2 - a2 * d1 - c1 * b2) as f64;
    let c = (a1 * c2 - a2 * c1) as f64;
    if a == 0_f64 {
        if b == 0_f64 {
            if c == 0_f64 {
                All
            }else {
                Suspects::None
            }
        }else if -c / b >= 0_f64 {
            Suspects::Some{suspects: vec![-c / b]}
        }else {
            Suspects::None
        }
    }else {
        let d = b * b - 4_f64 * a * c;
        if d < 0_f64 {
            Suspects::None
        }else if d.abs() <= 0.00000001_f64 {
            if -b / (a * 2_f64) >= 0_f64 {
                Suspects::Some{suspects: vec![-b / (a * 2_f64)]}
            }else {
                Suspects::None
            }
        }else {
            let s = d.sqrt();
            if (-b + s) / (a * 2_f64) < 0_f64 {
                Suspects::None
            }else if (-b - s) / (a * 2_f64) < 0_f64 {
                Suspects::Some{suspects: vec![(-b + s) / (a * 2_f64)]}
            }else {
                Suspects::Some{suspects: vec![(-b + s) / (a * 2_f64), (-b - s) / (a * 2_f64)]}
            }
        }
    }
}
fn flatten<T>(vec: &Vec<Vec<T>>) -> Vec<T> where T: Clone + Copy {
    let mut count = 0;
    for v in vec {
        count += v.len();
    }
    let mut result = Vec::with_capacity(count);
    for v in vec {
        for &f in v {
            result.push(f);
        }
    }
    result
}
fn lower_bound<T: PartialOrd>(vec: &Vec<T>, target: &T) -> usize {
    let mut left = 0;
    let mut right = vec.len();
    while left < right {
        let mid = (left + right) / 2;
        if vec[mid].partial_cmp(target).unwrap() == Ordering::Less {
            left = mid + 1;
        }else {
            right = mid;
        }
    }
    right
}
fn upper_bound<T: PartialOrd>(vec: &Vec<T>, target: &T) -> usize {
    let mut left = 0;
    let mut right = vec.len();
    while left < right {
        let mid = (left + right) / 2;
        if vec[mid].partial_cmp(target).unwrap() != Ordering::Greater {
            left = mid + 1;
        }else {
            right = mid;
        }
    }
    right
}
fn show<T>(vec: &Vec<T>) where T: Display {
    if vec.is_empty() {
        println!("[]")
    }else {
        print!("[{}", vec.first().unwrap());
        for i in 1 .. vec.len() {
            print!(", {}", vec[i]);
        }
        println!("]");
    }
}
fn solve(person: &Vec<Person>) -> usize {
    const EPS: f64 = 0.000001;
    let mut max = 0;
    /*
    for &a in person.iter() {
        let mut count =0;
        for &b in person.iter() {
            if a == b {
                count += 1;
            }
        }
        if max < count {
            max = count;
        }
    }
    */
    for a in 0 .. person.len() {
        for b in 0 .. a {
            if person[a] != person[b] {
                let mut count = 2;
                let mut suspects = Vec::new();
                for c in 0..person.len() {
                    if a != c && b != c {
                        match find_on_line_time(&person[a], &person[b], &person[c]) {
                            Suspects::All => {
                                count += 1;
                            },
                            Suspects::None => {}
                            Suspects::Some { suspects: vec } => {
                                for v in vec {
                                    suspects.push(v)
                                }
                            },
                        }
                    }
                }
                suspects.sort_by(|a, b| a.partial_cmp(b).unwrap());
                if count >= max {
                    max = count;
                }
                for &s in &suspects {
                    let c = upper_bound(&suspects, &(s + EPS)) - lower_bound(&suspects, &s);
                    match person[a].position_at(s) - person[b].position_at(s) {
                        PointF { x: x, y: y } if x.abs() >= EPS || y.abs() >= EPS => {
                            if count + c > max {
                                max = count + c;
                            }
                        }
                        _ => {
                            if count + 1 > max {
                                max = count + 1;
                            }
                        }
                    }
                }
            }
        }
    }
    let dummy = Person{initial: Point{x: 11, y: 11}, velocity: Vector{dx: 3, dy: 3}};
    for b in 0 .. person.len() {
        let mut count = 1;
        let mut suspects = Vec::new();
        for c in 0..person.len() {
            if b != c {
                match find_on_line_time(&dummy, &person[b], &person[c]) {
                    Suspects::All => {
                        count += 1;
                    },
                    Suspects::None => {}
                    Suspects::Some { suspects: vec } => {
                        for v in vec {
                            suspects.push(v)
                        }
                    },

                }
            }
        }
        suspects.sort_by(|a, b| a.partial_cmp(b).unwrap());
        if count > max {
            max = count;
        }
        for &s in &suspects {
            let c = upper_bound(&suspects, &(s + EPS)) - lower_bound(&suspects, &s);
            if count + c > max {
                max = count + c;
            }
        }
    }
    max
}