結果
問題 |
No.5022 XOR Printer
|
ユーザー |
![]() |
提出日時 | 2025-07-07 21:27:49 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 1,929 ms / 2,000 ms |
コード長 | 7,366 bytes |
コンパイル時間 | 214 ms |
コンパイル使用メモリ | 82,224 KB |
実行使用メモリ | 92,784 KB |
スコア | 5,213,702,237 |
最終ジャッジ日時 | 2025-07-26 12:31:49 |
合計ジャッジ時間 | 101,066 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
純コード判定しない問題か言語 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 50 |
ソースコード
"""Heuristic solver for the XOR Grid Maximization problem.""" from __future__ import annotations import random import sys import time from typing import List, Sequence, Tuple Cell = Tuple[int, int] def move_commands(start: Cell, end: Cell) -> List[str]: """Return a list of commands to move from ``start`` to ``end``. Movement is restricted to the four cardinal directions and no bounds checking is performed here. """ cmds: List[str] = [] i, j = start while i < end[0]: cmds.append("D") i += 1 while i > end[0]: cmds.append("U") i -= 1 while j < end[1]: cmds.append("R") j += 1 while j > end[1]: cmds.append("L") j -= 1 return cmds def manhattan(a: Cell, b: Cell) -> int: """Return the Manhattan distance between two cells.""" return abs(a[0] - b[0]) + abs(a[1] - b[1]) def optimize_path(start: Cell, points: Sequence[Cell], time_limit: float) -> List[Cell]: """Greedy nearest-neighbour path optimisation with a 2-opt improvement.""" remaining = list(points) path = [start] cur = start while remaining: nxt = min(remaining, key=lambda p: manhattan(cur, p)) path.append(nxt) remaining.remove(nxt) cur = nxt start_time = time.time() while time.time() - start_time < time_limit: improved = False for i in range(1, len(path) - 2): for j in range(i + 1, len(path) - 1): before = manhattan(path[i - 1], path[i]) + manhattan(path[j], path[j + 1]) after = manhattan(path[i - 1], path[j]) + manhattan(path[i], path[j + 1]) if after < before: path[i : j + 1] = reversed(path[i : j + 1]) improved = True break if improved: break if not improved: break return path[1:] # exclude start class State: """Holds board state, cursor position and accumulated operations.""" def __init__(self, board: List[List[int]]) -> None: self.board = board self.n = len(board) self.ops: List[str] = [] self.pos: Cell = (0, 0) self.hand = 0 # ------------------------------------------------------------------ # Operations # ------------------------------------------------------------------ def process_move(self, dest: Cell, op_limit: int) -> bool: """Move the cursor to ``dest`` if within the operation limit.""" cmds = move_commands(self.pos, dest) if len(self.ops) + len(cmds) > op_limit: return False self.ops.extend(cmds) self.pos = dest return True def process_copy(self, op_limit: int) -> bool: """Apply the copy operation on the current cell.""" if len(self.ops) >= op_limit: return False self.ops.append("C") self.hand ^= self.board[self.pos[0]][self.pos[1]] return True def process_write(self, op_limit: int) -> bool: """Apply the write operation on the current cell.""" if len(self.ops) >= op_limit: return False self.ops.append("W") self.board[self.pos[0]][self.pos[1]] ^= self.hand return True def get_score(self) -> int: """Return the total sum of all cell values.""" return sum(self.board[i][j] for i in range(self.n) for j in range(self.n)) class Solver: """Encapsulates the heuristic solution logic.""" def __init__(self, state: State, op_limit: int) -> None: self.state = state self.op_limit = op_limit - 10 self.op_limit_last = op_limit # ------------------------------------------------------------------ # Core solving logic # ------------------------------------------------------------------ def _prepare_bit(self, bit: int) -> None: """Randomly copy values until ``self.hand`` has ``bit`` set.""" attempts = 0 state = self.state while not (state.hand < (1 << (bit + 1)) and ((state.hand >> bit) & 1)): if attempts > state.n * state.n: break cell = (random.randrange(state.n), random.randrange(state.n)) if not state.process_move(cell, self.op_limit): break if not state.process_copy(self.op_limit): break attempts += 1 def _write_path(self, bit: int, path: Sequence[Cell]) -> None: """Follow ``path`` writing to cells whose ``bit`` is unset.""" state = self.state path_last = path[-1] for cell in path: if not state.process_move(cell, self.op_limit): break if cell == path_last and bit != 19: state.process_copy(self.op_limit) break if ((state.board[cell[0]][cell[1]] >> bit) & 1) == 0: if not state.process_write(self.op_limit): break def _finalize(self) -> None: """Perform a final sequence of operations to maximise the score.""" state = self.state state.process_copy(self.op_limit_last) min_val = min(state.board[i][j] for i in range(state.n) for j in range(state.n)) min_pos = min( [ (i, j) for i in range(state.n) for j in range(state.n) if state.board[i][j] == min_val ], key=lambda p: manhattan(state.pos, p), ) state.process_move(min_pos, self.op_limit_last) state.process_write(self.op_limit_last) state.process_copy(self.op_limit_last) state.process_write(self.op_limit_last) def solve(self) -> int: """Execute the heuristic and return the resulting score.""" state = self.state for bit in reversed(range(20)): self._prepare_bit(bit) target_cells = [ (i, j) for i in range(state.n) for j in range(state.n) if ((state.board[i][j] >> bit) & 1) == 0 ] if not target_cells: continue path = optimize_path(state.pos, target_cells, 0.1) self._write_path(bit, path) self._finalize() return state.get_score() def run_solver(n: int, t: int, board: List[List[int]]) -> Tuple[int, List[str]]: """Convenience wrapper for executing ``Solver``.""" state = State(board) solver = Solver(state, t) score = solver.solve() return score, state.ops def main() -> None: """Entry point when executed as a script.""" start_time = time.time() best_score = 0 best_ops: List[str] = [] n, t = map(int, sys.stdin.readline().split()) board_ini = [list(map(int, sys.stdin.readline().split())) for _ in range(n)] # randomly run code and get best score while time.time() - start_time < 1.85: score, ops = run_solver(n, t - 10, [row[:] for row in board_ini]) if len(ops) > t: continue if score > best_score: best_score = score best_ops = ops sys.stdout.write("\n".join(best_ops[:t]) + "\n") sys.stderr.write(f"{best_score} {len(best_ops)}\n") if __name__ == "__main__": main()