結果
問題 |
No.5022 XOR Printer
|
ユーザー |
![]() |
提出日時 | 2025-07-26 16:51:00 |
言語 | Java (openjdk 23) |
結果 |
AC
|
実行時間 | 1,918 ms / 2,000 ms |
コード長 | 16,352 bytes |
コンパイル時間 | 3,163 ms |
コンパイル使用メモリ | 104,888 KB |
実行使用メモリ | 65,116 KB |
スコア | 4,844,436,367 |
最終ジャッジ日時 | 2025-07-26 16:52:54 |
合計ジャッジ時間 | 101,385 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge6 |
純コード判定しない問題か言語 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 50 |
ソースコード
import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; import java.util.Scanner; public class Main { enum Move { U, D, L, R, W, C,; } private static Watch2 watch; private static final PCG_XSH_RR rng = new PCG_XSH_RR(System.nanoTime()); public static void main(final String[] args) { try (final Scanner sc = new Scanner(System.in)) { final int N = sc.nextInt(); watch = new Watch2(); final int T = sc.nextInt(); final int[][] A = new int[N][N]; for (int r = 0; r < N; r++) { for (int c = 0; c < N; c++) { A[r][c] = sc.nextInt(); } } final int[][] copyA = new int[N][N]; for (int r = 0; r < N; r++) { for (int c = 0; c < N; c++) { copyA[r][c] = A[r][c]; } } ArrayList<Move> solution = greedy(N, T, copyA); { for (int r = 0; r < N; r++) { for (int c = 0; c < N; c++) { copyA[r][c] = A[r][c]; } } int score = calculateScore(N, T, copyA, 0, 0, 0, solution); Utils.debug("score", score); } sa(N, T, A, copyA, solution); { for (int r = 0; r < N; r++) { for (int c = 0; c < N; c++) { copyA[r][c] = A[r][c]; } } int score = calculateScore(N, T, copyA, 0, 0, 0, solution); Utils.debug("score", score); } System.out.println(solution.stream().map(move -> move.name()) .reduce("", (sum, move) -> sum + move + "\n")); System.out.flush(); } catch (Exception e) { e.printStackTrace(); } } private static ArrayList<Move> greedy(final int N, final int T, int[][] A) throws AssertionError { ArrayList<Move> solution = new ArrayList<>(); { int r0 = 0; int c0 = 0; int v = 0; for (int shift = 19; shift >= 0; shift--) { final int mask = 1 << shift; if (solution.size() >= T) { break; } int bestR = -1; int bestC = -1; int bestR2 = -1; int bestC2 = -1; int bestR3 = -1; int bestC3 = -1; int bestR4 = -1; int bestC4 = -1; int bestDistance = (int) 1e9; for (int r = 0; r < N; r++) { for (int c = 0; c < N; c++) { if (((v ^ A[r][c]) & mask) != 0) { int distance = distance(r, c, r0, c0); if (distance < bestDistance) { bestR = r; bestC = c; bestR2 = -1; bestC2 = -1; bestR3 = -1; bestC3 = -1; bestR4 = -1; bestC4 = -1; bestDistance = distance; } } for (int r2 = 0; r2 < N; r2++) { for (int c2 = 0; c2 < N; c2++) { if (((v ^ A[r][c] ^ A[r2][c2]) & mask) != 0) { int distance = distance(r, c, r0, c0) + distance(r, c, r2, c2); if (distance < bestDistance) { bestR = r; bestC = c; bestR2 = r2; bestC2 = c2; bestR3 = -1; bestC3 = -1; bestR4 = -1; bestC4 = -1; bestDistance = distance; } } for (int r3 = 0; r3 < N; r3++) { for (int c3 = 0; c3 < N; c3++) { if (((v ^ A[r][c] ^ A[r2][c2] ^ A[r3][c3]) & mask) != 0) { int distance = distance(r, c, r0, c0) + distance(r, c, r2, c2) + distance(r2, c2, r3, c3); if (distance < bestDistance) { bestR = r; bestC = c; bestR2 = r2; bestC2 = c2; bestR3 = r3; bestC3 = c3; bestR4 = -1; bestC4 = -1; bestDistance = distance; } } } } } } } } if (bestR < 0) { break; } move(r0, c0, bestR, bestC, solution); r0 = bestR; c0 = bestC; if (bestR2 >= 0) { move(r0, c0, bestR2, bestC2, solution); r0 = bestR2; c0 = bestC2; if (bestR3 >= 0) { move(r0, c0, bestR3, bestC3, solution); r0 = bestR3; c0 = bestC3; if (bestR4 >= 0) { move(r0, c0, bestR4, bestC4, solution); r0 = bestR4; c0 = bestC4; } } } v = copy(r0, c0, v, A, solution); move(r0, c0, 0, 0, solution); r0 = 0; c0 = 0; for (int r = 0; r < N; r++) { if (r % 2 == 0) { for (int c = 0; c < N; c++) { if ((A[r][c] & mask) == 0) { move(r0, c0, r, c, solution); r0 = r; c0 = c; write(r, c, v, A, solution); } } } else { for (int c = N - 1; c >= 0; c--) { if ((A[r][c] & mask) == 0) { move(r0, c0, r, c, solution); r0 = r; c0 = c; write(r, c, v, A, solution); } } } } } } while (solution.size() > T) { solution.remove(solution.size() - 1); } return solution; } private static void write(int r, int c, int v, int[][] A, ArrayList<Move> solution) { solution.add(Move.W); A[r][c] = v ^ A[r][c]; } private static int copy(int r, int c, int v, int[][] A, ArrayList<Move> solution) { solution.add(Move.C); return v ^ A[r][c]; } private static void move(int r0, int c0, int r, int c, ArrayList<Move> solution) { while (r0 < r) { r0++; solution.add(Move.D); } while (r0 > r) { r0--; solution.add(Move.U); } while (c0 < c) { c0++; solution.add(Move.R); } while (c0 > c) { c0--; solution.add(Move.L); } } private static int distance(int r, int c, int r0, int c0) { return Math.abs(r - r0) + Math.abs(c - c0); } private static void sa(int N, int T, int[][] A, int[][] copyA, ArrayList<Move> solution) { final double startTemperature = 1e4; final double endTemperature = 1e1; double temperature = startTemperature; final double startTime = watch.elapsedSecond(); final double endTime = 1.75; for (int r = 0; r < N; r++) { for (int c = 0; c < N; c++) { copyA[r][c] = A[r][c]; } } int score = calculateScore(N, T, copyA, 0, 0, 0, solution); final int mask = (1 << 7) - 1; for (int iteration = 0;; iteration++) { if ((iteration & mask) == mask) { final double time = watch.elapsedSecond(); if (time > endTime) { System.err.println( "Iteration: " + iteration + ", Temperature: " + temperature + ", score: " + score); break; } temperature = startTemperature + (endTemperature - startTemperature) * ((time - startTime) / (endTime - startTime)); System.err.println("Iteration: " + iteration + ", Temperature: " + temperature + ", score: " + score); } final double random = 2 * rng.nextDouble(); if (random < 1) { final int i = rng.nextInt(solution.size()); int j = rng.nextInt(solution.size() - 1); if (j >= i) { j++; } if (i < j) { for (int k = i; k < j; k++) { solution.set(k, solution.set(k + 1, solution.get(k))); } } else { for (int k = i; k > j; k--) { solution.set(k, solution.set(k - 1, solution.get(k))); } } for (int r = 0; r < N; r++) { for (int c = 0; c < N; c++) { copyA[r][c] = A[r][c]; } } int deltaScore = calculateScore(N, T, copyA, 0, 0, 0, solution) - score; if (accept(temperature, deltaScore)) { score += deltaScore; } else { if (i < j) { for (int k = j; k > i; k--) { solution.set(k, solution.set(k - 1, solution.get(k))); } } else { for (int k = j; k < i; k++) { solution.set(k, solution.set(k + 1, solution.get(k))); } } } } else if (random < 2) { int i = rng.nextInt(solution.size()); Move current = solution.get(i); solution.set(i, Move.values()[rng.nextInt(Move.values().length)]); for (int r = 0; r < N; r++) { for (int c = 0; c < N; c++) { copyA[r][c] = A[r][c]; } } int deltaScore = calculateScore(N, T, copyA, 0, 0, 0, solution) - score; if (accept(temperature, deltaScore)) { score += deltaScore; } else { solution.set(i, current); } } } } private static boolean accept(double temperature, int deltaScore) { return deltaScore >= 0 || rng.nextDouble() < Math.exp(deltaScore / temperature); } private static int calculateScore(int N, int T, int[][] A, int r, int c, int v, ArrayList<Move> solution) { for (Move op : solution) { switch (op) { case U: { r--; if (r < 0) { return (int) -1e9; } break; } case D: { r++; if (r >= N) { return (int) -1e9; } break; } case L: { c--; if (c < 0) { return (int) -1e9; } break; } case R: { c++; if (c >= N) { return (int) -1e9; } break; } case W: { A[r][c] ^= v; break; } case C: { v ^= A[r][c]; break; } default: return (int) -1e9; } } return calculateScore(N, A); } private static int calculateScore(int N, int[][] A) { int score = 0; for (int r = 0; r < N; r++) { for (int c = 0; c < N; c++) { score += A[r][c]; } } return score; } } class PCG_XSH_RR { private long state = 5342; public PCG_XSH_RR(final long state) { this.state = state; } public int nextInt() { final long oldstate = state; state = oldstate * 6364136223846793005L + 521L; final int xorshift = (int) (((oldstate >>> 18) ^ oldstate) >>> 27); final int rotation = (int) (oldstate >>> 59); return (xorshift >>> rotation) | (xorshift << (-rotation & 31)); } public int nextInt(int n) { return (int) (n * nextDouble()); } public int nextInt2(int n) { final int k = 16; final int x = (nextInt() & ((1 << k) - 1)); return (x * n) >>> k; } public double nextDouble() { return (nextInt() >>> 1) * 4.6566128730773926E-10; } } class Watch2 { private final long start; public Watch2() { start = System.nanoTime(); } public double elapsedSecond() { return (System.nanoTime() - start) * 1e-9; } @Override public String toString() { final long elapsedSecond = (long) (1e3 * elapsedSecond()); return formatElapsedTimeWithUnits(elapsedSecond); } public static String formatElapsedTimeWithUnits(final long elapsedMillis) { final Duration duration = Duration.ofMillis(elapsedMillis); final long hours = duration.toHours(); final long minutes = duration.toMinutesPart(); final long seconds = duration.toSecondsPart(); final long millis = duration.toMillisPart(); final StringBuilder sb = new StringBuilder(); if (hours > 0) { sb.append(hours).append("h"); } if (minutes > 0 || hours > 0) { sb.append(minutes).append("m"); } sb.append(seconds); if (minutes > 0 || hours > 0) { } else { sb.append(".").append(String.format("%03d", millis)); } sb.append("s"); return sb.toString().trim(); } } class Utils { private Utils() { } public static final void debug(Object... o) { System.err.println(toString(o)); System.err.flush(); } public static final String toString(Object... o) { return Arrays.deepToString(o); } public static boolean isValid(int v, int min, int minUpper) { return v >= min && v < minUpper; } }