Ř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.

167 lines
4.6 KiB

use std::fs::File;
use byteorder::{LittleEndian, ReadBytesExt};
use rand::prelude::StdRng;
use rand::{SeedableRng, Rng, thread_rng};
const SIZE: usize = 16384;
struct City {
prices: Vec<u16>,
buyable_house_count: usize
}
impl City {
pub fn new(prices: Vec<u16>) -> Self {
let mut buyable_house_count = 0;
for &price in &prices {
if price > 0 {
buyable_house_count += 1;
}
}
City { prices, buyable_house_count }
}
pub fn get_price(&self, house: &House) -> u16 {
self.prices[house.y * SIZE + house.x]
}
pub fn get_price_xy(&self, x: usize, y: usize) -> u16 {
self.prices[y * SIZE + x]
}
pub fn is_house(&self, house: &House) -> bool {
self.get_price(&house) > 0
}
pub fn is_house_xy(&self, x: usize, y: usize) -> bool {
self.get_price_xy(x, y) > 0
}
pub fn get_house_count(&self) -> usize {
self.buyable_house_count
}
}
struct House {
x: usize,
y: usize,
}
impl House {
pub fn new(x: usize, y: usize) -> Self {
House { x, y }
}
}
fn main() {
let values = std::fs::read("01.in").unwrap();
let mut prices: Vec<u16> = Vec::new();
for y in 0..SIZE {
for x in 0..SIZE {
let price = (values[(y * SIZE + x) * 2] as u16) | ((values[(y * SIZE + x) * 2] as u16) << 8);
prices.push(price);
}
}
let city = City::new(prices);
println!("Created city");
loop {
let seed: u64 = thread_rng().gen();
eprintln!("Starting seed {}", seed);
let mut rng = StdRng::seed_from_u64(seed);
let mut reachable = vec![false; SIZE * SIZE];
let mut houses: Vec<House> = Vec::new();
let mut claimed_houses = 0;
loop {
loop {
let x = rng.gen_range(0..SIZE);
let y = rng.gen_range(0..SIZE);
let house = House::new(x, y);
if city.is_house_xy(x, y) && !reachable[y * SIZE + x] {
for y in (house.y as i32 - 500).max(0)..=(house.y as i32 + 500).min((SIZE - 1) as i32) {
for x in (house.x as i32 - 500).max(0)..=(house.x as i32 + 500).min((SIZE - 1) as i32) {
let index = y as usize * SIZE + x as usize;
if !reachable[index] {
reachable[index] = true;
if city.is_house_xy(x as usize, y as usize) {
claimed_houses += 1;
}
}
}
}
houses.push(house);
//eprintln!("{} houses", houses.len());
break;
}
}
let finished = claimed_houses == city.get_house_count();
if finished {
let price = get_price(&city, &houses);
eprintln!("Price: {}", price);
//print_houses(&houses);
break;
}
}
}
}
fn get_neighbors(city: &City, house: &House) -> Vec<House> {
let mut neighbors = Vec::new();
for y in (house.y as i32 - 500).max(0)..=(house.y as i32 + 500).min((SIZE - 1) as i32) {
for x in (house.x as i32 - 500).max(0)..=(house.x as i32 + 500).min((SIZE - 1) as i32) {
let house = House::new(x as usize, y as usize);
if city.get_price(&house) > 0 {
neighbors.push(house);
}
}
}
neighbors
}
fn print_houses(houses: &Vec<House>) {
eprintln!("{}", houses.len());
for house in houses {
eprintln!("{} {}", house.y, house.x);
}
}
fn get_price(city: &City, houses: &Vec<House>) -> u32 {
let mut price = 0u32;
for house in houses {
price += city.get_price(&house) as u32;
}
price
}
fn is_valid(city: &City, houses: &Vec<House>) -> Option<u32> {
let mut reachable = vec![false; SIZE * SIZE];
let mut price = 0u32;
for house in houses {
assert!(city.prices[house.y * SIZE + house.x] > 0);
for y in (house.y as i32 - 500).max(0)..=(house.y as i32 + 500).min((SIZE - 1) as i32) {
for x in (house.x as i32 - 500).max(0)..=(house.x as i32 + 500).min((SIZE - 1) as i32) {
reachable[y as usize * SIZE + x as usize] = true;
}
}
price += city.get_price(&house) as u32;
}
for y in 0..SIZE {
for x in 0..SIZE {
if !reachable[y * SIZE + x] && city.prices[y * SIZE + x] > 0 {
return None;
}
}
}
Some(price)
}