結果
問題 | No.199 星を描こう |
ユーザー | nebocco |
提出日時 | 2021-03-11 19:30:03 |
言語 | Rust (1.77.0 + proconio) |
結果 |
AC
|
実行時間 | 1 ms / 2,000 ms |
コード長 | 14,648 bytes |
コンパイル時間 | 12,470 ms |
コンパイル使用メモリ | 404,080 KB |
実行使用メモリ | 5,248 KB |
最終ジャッジ日時 | 2024-10-13 07:14:45 |
合計ジャッジ時間 | 13,862 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 1 ms
5,248 KB |
testcase_01 | AC | 1 ms
5,248 KB |
testcase_02 | AC | 1 ms
5,248 KB |
testcase_03 | AC | 1 ms
5,248 KB |
testcase_04 | AC | 1 ms
5,248 KB |
testcase_05 | AC | 1 ms
5,248 KB |
testcase_06 | AC | 1 ms
5,248 KB |
testcase_07 | AC | 1 ms
5,248 KB |
testcase_08 | AC | 1 ms
5,248 KB |
testcase_09 | AC | 1 ms
5,248 KB |
testcase_10 | AC | 1 ms
5,248 KB |
testcase_11 | AC | 1 ms
5,248 KB |
testcase_12 | AC | 1 ms
5,248 KB |
testcase_13 | AC | 1 ms
5,248 KB |
testcase_14 | AC | 1 ms
5,248 KB |
testcase_15 | AC | 1 ms
5,248 KB |
testcase_16 | AC | 1 ms
5,248 KB |
testcase_17 | AC | 1 ms
5,248 KB |
testcase_18 | AC | 1 ms
5,248 KB |
testcase_19 | AC | 1 ms
5,248 KB |
testcase_20 | AC | 1 ms
5,248 KB |
testcase_21 | AC | 1 ms
5,248 KB |
testcase_22 | AC | 1 ms
5,248 KB |
testcase_23 | AC | 1 ms
5,248 KB |
testcase_24 | AC | 1 ms
5,248 KB |
testcase_25 | AC | 1 ms
5,248 KB |
testcase_26 | AC | 1 ms
5,248 KB |
testcase_27 | AC | 1 ms
5,248 KB |
ソースコード
fn main() { let mut io = IO::new(); input!{ from io, ps: [(f64, f64); 5] } let pl = ps.iter().map(|&(x, y)| Point::new(x, y)).collect::<Vec<Point>>(); io.println( if convex_hull(&pl).len() == 5 { "YES" } else { "NO" } ); } pub fn convex_hull(points: &[Point]) -> Vec<Point> { let mut l = points.to_owned(); l.sort_by(|x, y| x.x().partial_cmp(&y.x()).unwrap()); let mut res1: Vec<Point> = Vec::new(); let mut res2: Vec<Point> = Vec::new(); for &x in &l { while res1.len() > 1 && res1[res1.len() - 2].area(&res1[res1.len() - 1], &x) <= 0. { res1.pop(); } res1.push(x); } res1.pop(); for &x in l.iter().rev() { while res2.len() > 1 && res2[res2.len() - 2].area(&res2[res2.len() - 1], &x) <= 0. { res2.pop(); } res2.push(x); } res2.pop(); res1.extend_from_slice(&res2); res1 } // ------------ geometry start ------------ #[derive(Clone, Copy)] pub struct Point(f64, f64); impl Point { pub const EPS: f64 = 0.000_000_001; pub fn new<T: Into<f64>>(x: T, y: T) -> Self { Self(x.into(), y.into()) } #[inline] pub fn x(&self) -> f64 { self.0 } #[inline] pub fn y(&self) -> f64 { self.1 } #[inline] pub fn arg(&self) -> f64 { self.1.atan2(self.0) } #[inline] pub fn norm(&self) -> f64 { (self.0.powi(2) + self.1.powi(2)).sqrt() } #[inline] pub fn dist(&self, rhs: &Self) -> f64 { (self - rhs).norm() } #[inline] pub fn unit(&self) -> Self { assert!(!self.is_zero(), "ゼロベクトルに法線はありませんよ?"); let d = self.norm(); Self(self.0 / d, self.1 / d) } #[inline] pub fn normal(&self) -> Self { Self(-self.1, self.0) } #[inline] pub fn dot(&self, rhs: &Self) -> f64 { self.0 * rhs.0 + self.1 * rhs.1 } #[inline] pub fn cross(&self, rhs: &Self) -> f64 { self.0 * rhs.1 - self.1 * rhs.0 } #[inline] pub fn area(&self, p: &Self, q: &Self) -> f64 { (p - self).cross(&(q - self)) } #[inline] pub fn rotate(&self, theta: f64) -> Self { Self ( self.0 * theta.cos() - self.1 * theta.sin(), self.0 * theta.sin() + self.1 * theta.cos(), ) } } pub struct Line(Point, Point); impl Line { pub fn new(p: Point, q: Point) -> Self { Self(p, q) } /// a * x + b * y = c pub fn from_equation(a: f64, b: f64, c: f64) -> Self { assert!(a.abs() < Point::EPS || a.abs() < Point::EPS, "不当な式ではありませんか?"); if a.abs() < Point::EPS { Self(Point::new(0., c / b), Point::new(1., c / b)) } else if b.abs() < Point::EPS { Self(Point::new(c / a, 0.), Point::new(c / a, 1.)) } else { Self(Point::new(0., c / b), Point::new(c / a, 0.)) } } #[inline] pub fn projection(&self, p: &Point) -> Point { self.0 + (self.0 - self.1) * Point::new( (p - self.0).dot(&(self.0 - self.1)) / (self.0 - self.1).norm(), 0. ) } #[inline] pub fn reflection(&self, p: &Point) -> Point { p + (self.projection(p) - p) * Point::new(2., 0.) } #[inline] pub fn is_orthogonal(&self, rhs: &Self) -> bool { (self.1 - self.0).dot(&(rhs.1 - rhs.0)) < Point::EPS } #[inline] pub fn is_parallel(&self, rhs: &Self) -> bool { (self.1 - self.0).cross(&(rhs.1 - rhs.0)) < Point::EPS } pub fn crosspoint(&self, rhs: &Self) -> Option<Point> { let d1 = (self.1 - self.0).cross(&(rhs.1 - rhs.0)); let d2 = (self.1 - self.0).cross(&(rhs.1 - rhs.0)); if self.is_parallel(rhs) { if d1.abs() < Point::EPS && d2.abs() < Point::EPS { Some(self.0) } else { None } } else { Some(rhs.0 + (rhs.1 - rhs.0) * Point::new(d2 / d1, 0.)) } } } pub struct Circle { pub center: Point, pub radius: f64, } impl Circle { pub fn new<T: Into<f64>>(x: T, y: T, r: T) -> Self { Self { center: Point::new(x, y), radius: r.into() } } #[allow(unused_variables)] pub fn intersection(&self, rhs: &Self) -> (Option<Point>, Option<Point>) { todo!() } } // ------------ impl arith start ------------ use std::fmt; impl fmt::Debug for Point { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "({:.6}, {:.6})", self.x(), self.y()) } } impl fmt::Display for Point { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "({:.6}, {:.6})", self.x(), self.y()) } } impl PartialEq for Point { fn eq(&self, rhs: &Self) -> bool { (self.0 - rhs.0).abs() < Self::EPS && (self.1 - rhs.1).abs() < Self::EPS } } impl Eq for Point {} impl PartialOrd for Point { fn partial_cmp(&self, rhs: &Self) -> Option<std::cmp::Ordering> { Some(self.cmp(rhs)) } } impl Ord for Point { fn cmp(&self, rhs: &Self) -> std::cmp::Ordering { if let Some(v) = self.arg().partial_cmp(&rhs.arg()) { v } else { std::cmp::Ordering::Equal } } } impl Add for Point { type Output = Point; fn add(self, rhs: Self) -> Self { Self(self.0 + rhs.0, self.1 + rhs.1) } } impl Sub for Point { type Output = Point; fn sub(self, rhs: Self) -> Self { Self(self.0 - rhs.0, self.1 - rhs.1) } } impl Mul for Point { type Output = Point; fn mul(self, rhs: Self) -> Self { Self( self.0 * rhs.0 - self.1 * rhs.1, self.0 * rhs.1 + self.1 * rhs.0 ) } } #[allow(clippy::suspicious_arithmetic_impl)] impl Div for Point { type Output = Point; fn div(self, rhs: Self) -> Self { assert!(!rhs.is_zero(), "ゼロベクトルで割ろうとしていませんか?"); let d = rhs.0.powi(2) + rhs.1.powi(2); Self( (self.0 * rhs.0 - self.1 * -rhs.1) / d, (self.0 * -rhs.1 + self.1 * rhs.0) / d ) } } impl Zero for Point { fn zero() -> Self { Self(0., 0.) } } impl<'a> Zero for &'a Point { fn zero() -> &'a Point { &Point(0., 0.) } } macro_rules! binop_ref { ($(impl $imp:ident, $method:ident)*) => { $( impl<'a> $imp<Point> for &'a Point { type Output = Point; fn $method(self, other: Point) -> Self::Output { $imp::$method(*self, other) } } impl<'a> $imp<&'a Point> for Point { type Output = Point; fn $method(self, other: &Point) -> Self::Output { $imp::$method(self, *other) } } impl<'a> $imp<&'a Point> for &'a Point { type Output = Point; fn $method(self, other: &Point) -> Self::Output { $imp::$method(*self, *other) } } )* }; } binop_ref! { impl Add, add impl Sub, sub impl Mul, mul impl Div, div } // ------------ impl arith end ------------ // ------------ geometry end ------------ // ------------ algebraic traits start ------------ use std::marker::Sized; use std::ops::*; /// 元 pub trait Element: Sized + Clone + PartialEq {} impl<T: Sized + Clone + PartialEq> Element for T {} /// 結合性 pub trait Associative: Magma {} /// マグマ pub trait Magma: Element + Add<Output=Self> {} impl<T: Element + Add<Output=Self>> Magma for T {} /// 半群 pub trait SemiGroup: Magma + Associative {} impl<T: Magma + Associative> SemiGroup for T {} /// モノイド pub trait Monoid: SemiGroup + Zero {} impl<T: SemiGroup + Zero> Monoid for T {} pub trait ComMonoid: Monoid + AddAssign {} impl<T: Monoid + AddAssign> ComMonoid for T {} /// 群 pub trait Group: Monoid + Neg<Output=Self> {} impl<T: Monoid + Neg<Output=Self>> Group for T {} pub trait ComGroup: Group + ComMonoid {} impl<T: Group + ComMonoid> ComGroup for T {} /// 半環 pub trait SemiRing: ComMonoid + Mul<Output=Self> + One {} impl<T: ComMonoid + Mul<Output=Self> + One> SemiRing for T {} /// 環 pub trait Ring: ComGroup + SemiRing {} impl<T: ComGroup + SemiRing> Ring for T {} pub trait ComRing: Ring + MulAssign {} impl<T: Ring + MulAssign> ComRing for T {} /// 体 pub trait Field: ComRing + Div<Output=Self> + DivAssign {} impl<T: ComRing + Div<Output=Self> + DivAssign> Field for T {} /// 加法単元 pub trait Zero: Element { fn zero() -> Self; fn is_zero(&self) -> bool { *self == Self::zero() } } /// 乗法単元 pub trait One: Element { fn one() -> Self; fn is_one(&self) -> bool { *self == Self::one() } } macro_rules! impl_integer { ($($T:ty,)*) => { $( impl Associative for $T {} impl Zero for $T { fn zero() -> Self { 0 } fn is_zero(&self) -> bool { *self == 0 } } impl<'a> Zero for &'a $T { fn zero() -> Self { &0 } fn is_zero(&self) -> bool { *self == &0 } } impl One for $T { fn one() -> Self { 1 } fn is_one(&self) -> bool { *self == 1 } } impl<'a> One for &'a $T { fn one() -> Self { &1 } fn is_one(&self) -> bool { *self == &1 } } )* }; } impl_integer! { i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize, } // ------------ algebraic traits end ------------ // ------------ io module start ------------ use std::io::{stdout, BufWriter, Read, StdoutLock, Write}; pub struct IO { iter: std::str::SplitAsciiWhitespace<'static>, buf: BufWriter<StdoutLock<'static>>, } impl IO { pub fn new() -> Self { let mut input = String::new(); std::io::stdin().read_to_string(&mut input).unwrap(); let input = Box::leak(input.into_boxed_str()); let out = Box::new(stdout()); IO { iter: input.split_ascii_whitespace(), buf: BufWriter::new(Box::leak(out).lock()), } } fn scan_str(&mut self) -> &'static str { self.iter.next().unwrap() } pub fn scan<T: Scan>(&mut self) -> <T as Scan>::Output { <T as Scan>::scan(self) } pub fn scan_vec<T: Scan>(&mut self, n: usize) -> Vec<<T as Scan>::Output> { (0..n).map(|_| self.scan::<T>()).collect() } pub fn print<T: Print>(&mut self, x: T) { <T as Print>::print(self, x); } pub fn println<T: Print>(&mut self, x: T) { self.print(x); self.print("\n"); } pub fn iterln<T: Print, I: Iterator<Item = T>>(&mut self, mut iter: I, delim: &str) { if let Some(v) = iter.next() { self.print(v); for v in iter { self.print(delim); self.print(v); } } self.print("\n"); } pub fn flush(&mut self) { self.buf.flush().unwrap(); } } impl Default for IO { fn default() -> Self { Self::new() } } pub trait Scan { type Output; fn scan(io: &mut IO) -> Self::Output; } macro_rules! impl_scan { ($($t:tt),*) => { $( impl Scan for $t { type Output = Self; fn scan(s: &mut IO) -> Self::Output { s.scan_str().parse().unwrap() } } )* }; } impl_scan!(i16, i32, i64, isize, u16, u32, u64, usize, String, f32, f64); impl Scan for char { type Output = char; fn scan(s: &mut IO) -> Self::Output { s.scan_str().chars().next().unwrap() } } pub enum Bytes {} impl Scan for Bytes { type Output = &'static [u8]; fn scan(s: &mut IO) -> Self::Output { s.scan_str().as_bytes() } } pub enum Chars {} impl Scan for Chars { type Output = Vec<char>; fn scan(s: &mut IO) -> Self::Output { s.scan_str().chars().collect() } } pub enum Usize1 {} impl Scan for Usize1 { type Output = usize; fn scan(s: &mut IO) -> Self::Output { s.scan::<usize>().wrapping_sub(1) } } impl<T: Scan, U: Scan> Scan for (T, U) { type Output = (T::Output, U::Output); fn scan(s: &mut IO) -> Self::Output { (T::scan(s), U::scan(s)) } } impl<T: Scan, U: Scan, V: Scan> Scan for (T, U, V) { type Output = (T::Output, U::Output, V::Output); fn scan(s: &mut IO) -> Self::Output { (T::scan(s), U::scan(s), V::scan(s)) } } impl<T: Scan, U: Scan, V: Scan, W: Scan> Scan for (T, U, V, W) { type Output = (T::Output, U::Output, V::Output, W::Output); fn scan(s: &mut IO) -> Self::Output { (T::scan(s), U::scan(s), V::scan(s), W::scan(s)) } } pub trait Print { fn print(w: &mut IO, x: Self); } macro_rules! impl_print_int { ($($t:ty),*) => { $( impl Print for $t { fn print(w: &mut IO, x: Self) { w.buf.write_all(x.to_string().as_bytes()).unwrap(); } } )* }; } impl_print_int!(i16, i32, i64, isize, u16, u32, u64, usize, f32, f64); impl Print for u8 { fn print(w: &mut IO, x: Self) { w.buf.write_all(&[x]).unwrap(); } } impl Print for &[u8] { fn print(w: &mut IO, x: Self) { w.buf.write_all(x).unwrap(); } } impl Print for &str { fn print(w: &mut IO, x: Self) { w.print(x.as_bytes()); } } impl Print for String { fn print(w: &mut IO, x: Self) { w.print(x.as_bytes()); } } impl<T: Print, U: Print> Print for (T, U) { fn print(w: &mut IO, (x, y): Self) { w.print(x); w.print(" "); w.print(y); } } impl<T: Print, U: Print, V: Print> Print for (T, U, V) { fn print(w: &mut IO, (x, y, z): Self) { w.print(x); w.print(" "); w.print(y); w.print(" "); w.print(z); } } mod neboccoio_macro { #[macro_export] macro_rules! input { (@start $io:tt @read @rest) => {}; (@start $io:tt @read @rest, $($rest: tt)*) => { input!(@start $io @read @rest $($rest)*) }; (@start $io:tt @read @rest mut $($rest:tt)*) => { input!(@start $io @read @mut [mut] @rest $($rest)*) }; (@start $io:tt @read @rest $($rest:tt)*) => { input!(@start $io @read @mut [] @rest $($rest)*) }; (@start $io:tt @read @mut [$($mut:tt)?] @rest $var:tt: [[$kind:tt; $len1:expr]; $len2:expr] $($rest:tt)*) => { let $($mut)* $var = (0..$len2).map(|_| $io.scan_vec::<$kind>($len1)).collect::<Vec<Vec<$kind>>>(); input!(@start $io @read @rest $($rest)*) }; (@start $io:tt @read @mut [$($mut:tt)?] @rest $var:tt: [$kind:tt; $len:expr] $($rest:tt)*) => { let $($mut)* $var = $io.scan_vec::<$kind>($len); input!(@start $io @read @rest $($rest)*) }; (@start $io:tt @read @mut [$($mut:tt)?] @rest $var:tt: $kind:tt $($rest:tt)*) => { let $($mut)* $var = $io.scan::<$kind>(); input!(@start $io @read @rest $($rest)*) }; (from $io:tt $($rest:tt)*) => { input!(@start $io @read @rest $($rest)*) }; } } // ------------ io module end ------------