結果
問題 | No.5016 Worst Mayor |
ユーザー |
|
提出日時 | 2025-04-29 22:57:12 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 388 ms / 2,000 ms |
コード長 | 6,934 bytes |
コンパイル時間 | 665 ms |
コンパイル使用メモリ | 82,836 KB |
実行使用メモリ | 101,528 KB |
スコア | 16,855,558,280 |
平均クエリ数 | 400.00 |
最終ジャッジ日時 | 2025-04-29 22:57:36 |
合計ジャッジ時間 | 23,059 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
純コード判定しない問題か言語 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 50 |
ソースコード
import copy import random from time import perf_counter import argparse import sys import math # --- Constants --- H = 14 INITIAL_MONEY = 10**6 INITIAL_COLLABORATORS = 1 NORMAL_COST = 1.0 HIGHWAY_COST = 0.223 HIGHWAY_REVENUE = 30 FUNDRAISE_AMOUNT = 50000 HIGHWAY_BUILD_BASE_COST = 10**7 def floyd_warshall_init(H, normal_cost): V = H * H INF = float('inf') # distance and highway-count matrices dist = [[INF] * V for _ in range(V)] hw_count = [[0] * V for _ in range(V)] # self-distance for u in range(V): dist[u][u] = 0.0 # grid adjacency for r in range(H): for c in range(H): u = r * H + c for dr, dc in [(0,1),(0,-1),(1,0),(-1,0)]: nr, nc = r + dr, c + dc if 0 <= nr < H and 0 <= nc < H: v = nr * H + nc dist[u][v] = normal_cost # initial APSP for k in range(V): for i in range(V): dik = dist[i][k] hik = hw_count[i][k] for j in range(V): nd = dik + dist[k][j] if nd < dist[i][j]: dist[i][j] = nd hw_count[i][j] = hik + hw_count[k][j] return dist, hw_count class TimeKeeper: def __init__(self): self.start_time = perf_counter() def is_time_over(self, LIMIT): return (perf_counter() - self.start_time) >= LIMIT def time_now(self): return (perf_counter() - self.start_time) class Solver: def __init__(self, N, T, citizens, DEBUG): self.N = N self.T = T self.citizens = citizens self.DEBUG = DEBUG # --- 状態変数 --- self.money = INITIAL_MONEY self.collaborators = INITIAL_COLLABORATORS self.highways = set() self.day = 0 self.actions = [] self.daily_revenue = 0 # APSP 用行列の初期化 self.V = H * H self.dist, self.hw_count = floyd_warshall_init(H, NORMAL_COST) def update_apsp_edge(self, u, v): # 新しい高速道路エッジ (u<->v) を反映 V = self.V w = HIGHWAY_COST # 直接距離更新 self.dist[u][v] = w self.dist[v][u] = w self.hw_count[u][v] = 1 self.hw_count[v][u] = 1 # 差分更新 for i in range(V): di_u = self.dist[i][u] hi_u = self.hw_count[i][u] di_v = self.dist[i][v] hi_v = self.hw_count[i][v] for j in range(V): # i -> u -> v -> j nd = di_u + w + self.dist[v][j] nh = hi_u + 1 + self.hw_count[v][j] if nd < self.dist[i][j]: self.dist[i][j] = nd self.hw_count[i][j] = nh # i -> v -> u -> j nd2 = di_v + w + self.dist[u][j] nh2 = hi_v + 1 + self.hw_count[u][j] if nd2 < self.dist[i][j]: self.dist[i][j] = nd2 self.hw_count[i][j] = nh2 def execute_action(self, action): t = action[0] if t == 1: # 道路建設 r1, c1, r2, c2 = action[1:] cost = int(HIGHWAY_BUILD_BASE_COST / math.sqrt(self.collaborators)) if self.money >= cost: self.money -= cost n1 = r1 * H + c1 n2 = r2 * H + c2 edge = tuple(sorted((n1, n2))) self.highways.add(edge) # APSP の差分更新 self.update_apsp_edge(n1, n2) else: print(f"ERROR no money: {action=}") exit() elif t == 2: # 協力者集め self.collaborators += 1 elif t == 3: # 資金集め self.money += FUNDRAISE_AMOUNT return def update_daily_revenue(self): # APSP の hw_count を使って収益を計算 total = 0 for a, b, c, d in self.citizens: s = a * H + b t = c * H + d total += self.hw_count[s][t] self.daily_revenue = 2 * HIGHWAY_REVENUE * total return def choose_action(self): if self.collaborators < 50: return [2] if self.day >= 300: return [3] cost = int(HIGHWAY_BUILD_BASE_COST / math.sqrt(self.collaborators)) if self.money < cost: return [3] # 道路建設 road = [] # s = [6,7,5,8,4,9,3,10,2,11,1] # 0-10 s = [6,7,5,8,4,9,3,10,2,11,1,12,0] # 0-12 p0 = 4 p1 = 8 for i in s: a, b, c, d = i, p0, i+1, p0 road.append((a, b, c, d)) for i in s: a, b, c, d = p0, i, p0, i+1 road.append((a, b, c, d)) for i in s: a, b, c, d = i, p1, i+1, p1 road.append((a, b, c, d)) for i in s: a, b, c, d = p1, i, p1, i+1 road.append((a, b, c, d)) # for i in s: # a, b, c, d = i, 6, i+1, 6 # road.append((a, b, c, d)) # for i in s: # a, b, c, d = 6, i, 6, i+1 # road.append((a, b, c, d)) rid = len(self.highways) if rid >= len(road): return [3] else: a, b, c, d = road[rid] return [1, a, b, c, d] def solve(self, tk, LIMIT): for day in range(self.T): self.day = day if not self.DEBUG: M, C = map(int, input().split()) self.money, self.collaborators = M, C action = self.choose_action() self.actions.append(action) self.execute_action(action) # DEBUG モードで収益更新 if self.DEBUG and action[0] == 1: self.update_daily_revenue() # 収益反映 self.money += self.daily_revenue # デバッグ出力 # print(f"day={day} action={action} money={self.money} cols={self.collaborators} highways={len(self.highways)} revenue={self.daily_revenue}", file=sys.stderr) # 出力 if action[0] == 1: a, b, c, d = action[1:] print(1, a+1, b+1, c+1, d+1) else: print(action[0]) return self.actions, self.money def main(DEBUG): tk = TimeKeeper() LIMIT = 0.8 N, T = map(int, input().split()) citizens = [] for _ in range(N): a, b, c, d = map(int, input().split()) citizens.append([a-1, b-1, c-1, d-1]) solver = Solver(N, T, citizens, DEBUG) ans, sc = solver.solve(tk, LIMIT) print("SC", sc, file=sys.stderr) if __name__ == '__main__': parser = argparse.ArgumentParser(description='Debug mode') parser.add_argument('--debug', action='store_true', help='Enable debug mode') args = parser.parse_args() main(args.debug)