Řešení KSP úlohy 33-3-4 Obsazování území https://ksp.mff.cuni.cz/h/ulohy/33/zadani3.html#task-33-3-4
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
3.3 KiB

use crate::city::{Rectangle, HOUSE_RANGE, House, HouseLayout, City};
pub struct Subcity {
city: City,
bought_houses: Vec<House>,
x_offset: usize,
y_offset: usize
}
impl Subcity {
pub fn city(&self) -> &City {
&self.city
}
pub fn bought_houses(&self) -> &Vec<House> {
&self.bought_houses
}
pub fn x_offset(&self) -> usize {
self.x_offset
}
pub fn y_offset(&self) -> usize {
self.y_offset
}
pub fn to_full_houses(&self, subcity_houses: &Vec<House>) -> Vec<House> {
let mut full_houses: Vec<House> = Vec::new();
for house in subcity_houses {
full_houses.push(House::new(house.x + self.x_offset, house.y + self.y_offset))
}
for house in &self.bought_houses {
full_houses.push(*house)
}
full_houses
}
}
/// Creates a new city that is a subset of the original city.
/// The provided houses and houses they cover are removed. If there is an empty margin
/// around uncovered houses, it is removed - this may result in a smaller city.
pub fn build_subcity(city: &City, bought_houses: &[House]) -> Subcity {
let mut covered = vec![false; city.width() * city.height()];
for house in bought_houses {
assert!(city.is_house(*house));
let range_rect = house.range_rectangle(city);
for y in range_rect.top..=range_rect.bottom {
for x in range_rect.left..=range_rect.right {
covered[y as usize * city.width() + x as usize] = true;
}
}
}
// Inclusive bounds for uncovered houses in the new subcity
let mut min_x = None;
let mut min_y = None;
let mut max_x = None;
let mut max_y = None;
for y in 0..city.height() {
for x in 0..city.width() {
if !covered[y * city.width() + x] && city.is_house_xy(x, y) {
min_x = Some(min_x.unwrap_or(usize::MAX).min(x));
min_y = Some(min_y.unwrap_or(usize::MAX).min(y));
max_x = Some(max_x.unwrap_or(usize::MIN).max(x));
max_y = Some(max_x.unwrap_or(usize::MIN).max(y));
}
}
}
if min_x.is_none() {
assert!(min_y.is_none());
assert!(max_x.is_none());
assert!(max_y.is_none());
return Subcity {
city: City::new(Vec::new(), 0, 0),
bought_houses: bought_houses.iter().map(|&h| h).collect(),
x_offset: 0,
y_offset: 0,
};
}
let min_x = min_x.unwrap();
let min_y = min_y.unwrap();
let max_x = max_x.unwrap();
let max_y = max_y.unwrap();
let width = max_x - min_x + 1;
let height = max_y - min_y + 1;
let mut prices = vec![0; height * width];
for y in 0..height {
for x in 0..width {
let original_x = min_x + x;
let original_y = min_y + y;
// Copy prices for uncovered tiles, the covered tiles default to 0 - non-houses.
if !covered[original_y * city.width() + original_x] {
prices[y * width + x] = city.get_price_xy(original_x, original_y)
}
}
}
Subcity {
city: City::new(prices, width, height),
bought_houses: bought_houses.iter().map(|&h| h).collect(),
x_offset: min_x,
y_offset: min_y
}
}