#!/usr/bin/env python3 import sys import math import copy outLines = [] def log(*data): if True: print(*data) def output(*values): global outLines outLines.append(' '.join([str(val) for val in values])) def distance(A, B): return math.ceil(math.sqrt(pow(B[0] - A[0], 2) + pow(B[1] - A[1], 2))) class Product: ALL = [] def __init__(self, weight): self.id = len(self.ALL) self.ALL.append(self) self.weight = weight def get(pid): return __class__.ALL[pid] def len(): return len(__class__.ALL) class Warehouse: ALL = [] def __init__(self, pos, items): self.id = len(self.ALL) self.ALL.append(self) self.pos = pos self.items = items def get(pid): return __class__.ALL[pid] def len(): return len(__class__.ALL) class Client: ALL = [] def __init__(self, pos, needs): self.id = len(self.ALL) self.ALL.append(self) self.pos = pos self.needs = needs def satisfied(self): return len(self.needs) == 0 def get(pid): return __class__.ALL[pid] def len(): return len(__class__.ALL) class Drone: ALL = [] PAYLOAD = 0 def __init__(self): self.id = len(self.ALL) self.ALL.append(self) self.pos = Warehouse.get(0).pos self.items = [] self.avail = 0 self.tasks = [] def weight(self): s = 0 for i in self.items: s += Product.get(i).weight return s def busyFor(self, time): self.avail += time assert(self.avail < T) def available(self): return self.avail <= turn def load(self, warehouse, product, qt): assert(self.available()) if (self.pos != warehouse.pos): self.busyFor(distance(self.pos, warehouse.pos)) self.pos = warehouse.pos for q in range(qt): warehouse.items.remove(product.id) self.items.append(product.id) self.busyFor(1) assert(self.weight() <= __class__.PAYLOAD) log("Drone", self.id, "loads", qt, "of", product.id, "from warehouse", warehouse.id, "→", self.avail) output(self.id, 'L', warehouse.id, product.id, qt) def unload(self, warehouse, product, qt): assert(self.available()) if (self.pos != warehouse.pos): self.busyFor(distance(self.pos, warehouse.pos)) self.pos = warehouse.pos for q in range(qt): self.items.remove(product.id) warehouse.items.append(product.id) self.busyFor(1) log("Drone", self.id, "unloads", qt, "of", product.id, "to warehouse", warehouse.id, "→", self.avail) output(self.id, 'U', warehouse.id, product.id, qt) def deliver(self, client, product, qt): assert(self.available()) if (self.pos != client.pos): self.busyFor(distance(self.pos, client.pos)) self.pos = client.pos for q in range(qt): self.items.remove(product.id) client.needs.remove(product.id) self.busyFor(1) log("Drone", self.id, "delivers", qt, "of", product.id, "to client", client.id, "→", self.avail) output(self.id, 'D', client.id, product.id, qt) if client.satisfied(): global score score += math.ceil((T-(self.avail-1))/T*100) log("Client", client.id, "satisfied!", "New score:", score) def wait(self, turns=1): assert(self.available()) self.busyFor(1) log("Drone", self.id, "waits", turns, "turn" + ('s' if turns >= 2 else ''), "→", self.avail) output(self.id, 'W', turns) def get(pid): return __class__.ALL[pid] def len(): return len(__class__.ALL) X = 0 # Nb rows Y = 0 # Nb columns T = 0 # Deadline turn = 0 # Turn score = 0 # Score def readFile(filename): global X, Y, T with open(filename, 'r') as f: # Parameters X, Y, D, T, Drone.PAYLOAD = [int(i) for i in f.readline().split(' ')] # Products P = int(f.readline()) weights = [int(i) for i in f.readline().split(' ')] assert(len(weights) == P) for w in weights: Product(w) # Warehouses for i in range(0, int(f.readline())): pos = [int(i) for i in f.readline().split(' ')] qtItems = [int(i) for i in f.readline().split(' ')] assert(len(qtItems) == P) items = [] for p in range(P): for i in range(qtItems[p]): items.append(p) Warehouse(pos, items) # Clients for i in range(0, int(f.readline())): pos = [int(i) for i in f.readline().split(' ')] N = int(f.readline()) needs = [int(i) for i in f.readline().split(' ')] assert(len(needs) == N) Client(pos, needs) # Create drones for d in range(D): Drone() readFile(sys.argv[1]) def newTurn(): global turn # Finishing turn for drone in [drone for drone in Drone.ALL if drone.available()]: drone.wait() # New turn turn += 1 log("--- Turn", turn) availableDrones = [str(drone.id) for drone in Drone.ALL if drone.available()] log("Drones", ", ".join(availableDrones), "("+str(len(availableDrones))+")", "are available") try: d = 0 N = Client.get(0).needs.copy() for n in N: Drone.get(d).load(Warehouse.get(0), Product.get(n), 1) d += 1 newTurn() d = 0 for n in N: Drone.get(d).deliver(Client.get(0), Product.get(Drone.get(d).items[0]), 1) d += 1 except KeyboardInterrupt: pass with open(sys.argv[1] + 'o', 'w') as f: f.write(str(len(outLines)) + '\n' + '\n'.join(outLines) + '\n') print("Score:", score)