import sys import time import random import math random.seed(42) INF = 10**18 alpha = 5 alpha2 = alpha * alpha def eprint(*args, **kwargs): print(*args, file=sys.stderr, **kwargs) class TimeKeeper: """ 時間を管理するクラス 時間制限を秒単位で指定してインスタンスをつくる """ def __init__(self, time_threshold) -> None: self.start_time_ = time.time() self.time_threshold_ = time_threshold def isTimeOver(self) -> bool: """ インスタンスを生成した時から指定した時間制限を超過したか判断する 超過している場合にTrue """ return time.time() - self.start_time_ - self.time_threshold_ >= 0 def time_msec(self) -> int: """経過時間をミリ秒単位で返す""" return int((time.time() - self.start_time_) * 1000) def time_sec(self) -> int: """経過時間を秒単位で返す(time_msecの使用を推奨)""" return time.time()-self.start_time_ class Input: def __init__(self, N:int, M:int, ab:list) -> None: self.N = N self.M = M self.ab = ab class Parser: def __init__(self, input_type:int): self.flag = input_type def parse(self): if self.flag == -1: inp:Input = self.parse_input() else: inp:Input = self.parse_input_file(self.flag) return inp def parse_input(self) -> Input: N,M = map(int,input().split()) ab = [list(map(int,input().split())) for i in range(N)] return Input(N,M,ab) def parse_input_file(self,num) -> Input: cnt = str(num).zfill(4) PATH = f"./in/{cnt}.txt" with open(PATH) as f: l = [s.strip() for s in f.readlines()] N, M = map(int,l[0].split()) ab = [list(map(int,s.split())) for s in l[1:]] return Input(N, M, ab) class Transit: def __init__(self, id:int, x:int, y:int, type:int) -> None: """ id:int id of planet or station x:int x coordinate y:int y coordinate type:int 1 planet, 2 station """ self.id = id self.x = x self.y = y self.type = type def __str__(self) -> str: return f"({self.id},{self.x},{self.y},{self.type})" class State: def __init__(self, order:list, q_planets:list, q_stations:list) -> None: """ order:list visited order q_stations:list[(int,int)] coordinates of space station """ self.order = order self.q_planets = q_planets self.q_stations = q_stations def cal_dist(self, v1:Transit, v2:Transit) -> float: """ return distance between v1 and v2 weighted by coefficient """ x1,y1 = v1.x, v1.y x2,y2 = v2.x, v2.y coef = 1 # station to station if v1.type == 1 and v2.type == 1: coef = alpha2 # planet to planet elif v1.type == 2 or v2.type == 2: coef = alpha # planet to station or station to planet d = ((x1-x2)**2+(y1-y2)**2) * coef return d def cal_score(self): score = 0 for i in range(len(self.order)-1): score += self.cal_dist(self.order[i], self.order[i+1]) return int(pow(10,9)/(1000+score**0.5)) class Output: def __init__(self, state:State) -> None: self.order = state.order self.q_stations = state.q_stations def ans(self): for transition in self.q_stations: print(transition.x, transition.y) print(len(self.order)) for transition in self.order: print(transition.type, transition.id+1) class Solver: def __init__(self, state:State) -> None: self.state = state def solve(self): self.state.order.append(self.state.q_planets[0]) visited = [0]*len(self.state.q_planets) visited[0] = 1 now = self.state.q_planets[0] next = Transit(-1,-1,-1,-1) while sum(visited) < len(self.state.q_planets): d_min = INF for transtion in self.state.q_planets: if visited[transtion.id] == 1: continue d = self.state.cal_dist(now, transtion) if d_min > d: d_min = d next = transtion if now.type != 2: #station to stationを許可するときはこのif文を消す 要改善 for transtion in self.state.q_stations: if now == transtion: continue d = self.state.cal_dist(now, transtion) if d_min > d: d_min = d next = transtion now = next self.state.order.append(next) if next.type == 1: visited[next.id] = 1 self.state.order.append(self.state.q_planets[0]) return self.state def main(): parser = Parser(-1) input = parser.parse() q_planets = [] for i in range(input.N): q_planets.append(Transit(id = i, x = input.ab[i][0], y = input.ab[i][1], type = 1)) best_score = -1 best_ans = None timeKeeper = TimeKeeper(0.9) while not timeKeeper.isTimeOver(): order = [] q_stations = [] for i in range(input.M): q_stations.append(Transit(id = i,x = random.randrange(100,900),y = random.randrange(100,900),type = 2)) state = State(order,q_planets,q_stations) solver = Solver(state) ans = solver.solve() score = ans.cal_score() eprint(score) if score > best_score: best_score = score best_ans = ans eprint(best_score) output = Output(best_ans) output.ans() if __name__ == "__main__": main()