有n张地图(已知名称和某两个对角线端点的坐标)和m个地名(已知名称和坐标),还有q个查询。每张地图都是边平行于坐标轴的矩形,比例定义为高度除以宽度的值。每个查询包含一个地名和详细等级i。面积相同的地图总是属于同一个详细等级。假定包含此地名的地图中一共有k种不同的面积,则合法的详细等级为1~k(其中1最不详细,k最详细,面积越小越详细)。如果详细等级i的地图不止一张,则输出地图中心和查询地名最接近的一张;如果还有并列的,地图长宽比应尽量接近0.75(这是Web浏览器的比例);如果还有并列,查询地名和地图右下角的坐标应最远(对应最少的滚动条移动);如果还有并列,则输出x坐标最小的一个。如果查询的地名不存在或者没有地图包含它,或者i超过包含它的地图的最大详细等级,应报告查询非法(并输出包含它的最详细地图名称,如果存在)。
样例:
输入
MAPS
BayArea -6.0 12.0 -11.0 5.0
SantaClara 4.0 9.0 -3.5 2.5
SanJoseRegion -3.0 10.0 11.0 3.0
CenterCoast -5.0 11.0 1.0 -8.0
SanMateo -5.5 4.0 -12.5 9.0
NCalif -13.0 -7.0 13.0 15.0
LOCATIONS
Monterey -4.0 2.0
SanJose -1.0 7.5
Fresno 7.0 0.1
SanFrancisco -10.0 8.6
SantaCruz -4.0 2.0
SanDiego 13.8 -19.3
REQUESTS
SanJose 3
SanFrancisco 2
Fresno 2
Stockton 1
SanDiego 2
SanJose 4
SantaCruz 3
END
输出
SanJose at detail level 3 using SanJoseRegion
SanFrancisco at detail level 2 using BayArea
Fresno at detail level 2 no map at that detail level; using NCalif
Stockton at detail level 1 unknown location
SanDiego at detail level 2 no map contains that location
SanJose at detail level 4 using SantaClara
SantaCruz at detail level 3 no map at that detail level; using CenterCoast
解法:
use std::{collections::HashMap, io};
#[derive(Debug)]
struct Map {
name: String,
coord1: (f64, f64),
coord2: (f64, f64),
area: f64,
mid_coord: (f64, f64),
ratio: f64,
}
impl Map {
fn contain(&self, coord: (f64, f64)) -> bool {
let minx = self.coord1.0.min(self.coord2.0);
let maxx = self.coord1.0.max(self.coord2.0);
let miny = self.coord1.1.min(self.coord2.1);
let maxy = self.coord1.1.max(self.coord2.1);
if coord.0 >= minx && coord.0 <= maxx && coord.1 >= miny && coord.1 <= maxy {
true
} else {
false
}
}
fn mid_dist(&self, coord: (f64, f64)) -> f64 {
(self.mid_coord.0 - coord.0).powf(2.0) + (self.mid_coord.1 - coord.1).powf(2.0)
}
fn rb_dist(&self, coord: (f64, f64)) -> f64 {
let r = self.coord1.0.max(self.coord2.0);
let b = self.coord1.1.min(self.coord2.1);
(r - coord.0) * (r - coord.0) + (b - coord.1) * (b - coord.1)
}
}
#[derive(Debug)]
struct Request {
name: String,
detail_level: usize,
}
fn main() {
let mut buf = String::new();
io::stdin().read_line(&mut buf).unwrap();
let mut maps: Vec<Map> = vec![];
loop {
let mut buf = String::new();
io::stdin().read_line(&mut buf).unwrap();
if buf.trim() == "LOCATIONS" {
break;
}
let mut it = buf.split_whitespace();
let name = it.next().unwrap();
let v: Vec<f64> = it.map(|x| x.parse().unwrap()).collect();
let coord1 = (v[0], v[1]);
let coord2 = (v[2], v[3]);
maps.push(Map {
name: name.to_string(),
coord1: coord1,
coord2: coord2,
area: (coord1.0 - coord2.0).abs() * (coord1.1 - coord2.1).abs(),
mid_coord: ((coord1.0 + coord2.0) / 2.0, (coord1.1 + coord2.1) / 2.0),
ratio: (coord1.0 - coord2.0).abs() / (coord1.1 - coord2.1).abs(),
});
}
let mut location_maps: HashMap<String, Vec<&Map>> = HashMap::new();
loop {
let mut buf = String::new();
io::stdin().read_line(&mut buf).unwrap();
if buf.trim() == "REQUESTS" {
break;
}
let mut it = buf.split_whitespace();
let name = it.next().unwrap();
let v: Vec<f64> = it.map(|x| x.parse().unwrap()).collect();
let coord = (v[0], v[1]);
let mut in_maps: Vec<&Map> = vec![];
for map in maps.iter() {
if map.contain(coord) {
in_maps.push(map);
}
}
in_maps.sort_by(|a, b| {
if a.area != b.area {
b.area.partial_cmp(&a.area).unwrap()
} else if a.mid_dist(coord) != b.mid_dist(coord) {
a.mid_dist(coord).partial_cmp(&b.mid_dist(coord)).unwrap()
} else if a.ratio != b.ratio {
(a.ratio - 0.75)
.abs()
.partial_cmp(&(b.ratio - 0.75).abs())
.unwrap()
} else if a.rb_dist(coord) != b.rb_dist(coord) {
b.rb_dist(coord).partial_cmp(&a.rb_dist(coord)).unwrap()
} else {
a.coord1
.0
.min(a.coord2.0)
.partial_cmp(&b.coord1.0.min(b.coord2.0))
.unwrap()
}
});
location_maps.insert(name.to_string(), in_maps);
}
let mut requests: Vec<Request> = vec![];
loop {
let mut buf = String::new();
io::stdin().read_line(&mut buf).unwrap();
if buf.trim() == "END" {
break;
}
let mut it = buf.split_whitespace();
let name = it.next().unwrap();
let detail_level: usize = it.next().unwrap().parse().unwrap();
requests.push(Request {
name: name.to_string(),
detail_level,
});
}
for r in requests.iter() {
let name = &r.name;
let detail_level = r.detail_level;
print!("{} at detail level {} ", name, detail_level);
if let Some(v) = location_maps.get(name) {
if v.len() == 0 {
println!("no map contains that location");
} else {
let mut level = 1;
for j in 0..v.len() {
if level == detail_level {
println!("using {}", v[j].name);
break;
}
if j + 1 < v.len() && v[j].area != v[j + 1].area {
level += 1;
}
}
if level != detail_level {
println!(
"no map at that detail level; using {}",
v.last().unwrap().name
);
}
}
} else {
println!("unknown location");
}
}
}