Submission #8817548


Source Code Expand

import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Scanner;
import java.util.SplittableRandom;

public final class Main {
	private static final long startTime = System.currentTimeMillis();
	private static final boolean DEBUG = false;
	private static final long TL = 1000;
	private static final Scanner sc = new Scanner(System.in);
	private static final SplittableRandom rnd = new SplittableRandom(42);
	private static final int N = 1000;
	private static final int S = 1000;
	private static final int K = 20;
	private int[] x = new int[N], y = new int[N], c = new int[N];
	private boolean[][] used = new boolean[N][N], gEn = new boolean[N][N];
	private int[][] usedCount = new int[N][N], unusedCount = new int[N][N], g = new int[N][];
	private int[][] trees = new int[S][K - 1];

	public static void main(String[] args) {
		new Main().solve();
	}

	void solve() {
		sc.nextLine();
		for (int i = 0; i < N; i++) {
			x[i] = Integer.parseInt(sc.next());
			y[i] = Integer.parseInt(sc.next());
			c[i] = Integer.parseInt(sc.next());
		}
		for (int i = 0; i < S; i++) {
			for (int j = 0; j < K - 1; j++) {
				trees[i][j] = Integer.parseInt(sc.next()) - 1;
			}
		}
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < i; j++) {
				gEn[i][j] = gEn[j][i] = sq(x[i] - x[j]) + sq(y[i] - y[j]) <= sq(c[i] + c[j]);
			}
		}
		for (int i = 0; i < N; i++) {
			int count = 0;
			for (int j = 0; j < N; j++) {
				if (gEn[i][j]) ++count;
			}
			int[] row = new int[count];
			for (int j = 0, p = 0; j < N; j++) {
				if (gEn[i][j]) {
					row[p++] = j;
				}
			}
			g[i] = row;
		}
		long worstTime = 0;
		long beforeTime = System.currentTimeMillis();
		Solution bestSol = null;
		for (int turn = 0; ; turn++) {
			if (beforeTime + worstTime - startTime > TL) {
				debug("turn:%d", turn);
				break;
			}
			Solution sol = findSolution();
			debug("score:%d", sol.score);
			if (bestSol == null || sol.score > bestSol.score) {
				bestSol = sol;
			}
			long curTime = System.currentTimeMillis();
			worstTime = Math.max(worstTime, curTime - beforeTime);
			beforeTime = curTime;
		}
		PrintWriter writer = new PrintWriter(System.out);
		writer.println(bestSol.a.size);
		for (int i = 0; i < bestSol.a.size; i++) {
			writer.println((bestSol.a.a[i] + 1) + " " + (bestSol.b.a[i] + 1));
		}
		for (int i = 0; i < S; i++) {
			for (int j = 0; j < K - 1; j++) {
				writer.print((bestSol.v[i][j] + 1) + " ");
			}
			writer.println(bestSol.v[i][K - 1] + 1);
		}
		writer.flush();
		System.err.println("score:" + bestSol.score);
	}

	Solution findSolution() {
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				used[i][j] = false;
				usedCount[i][j] = 0;
				unusedCount[i][j] = 0;
			}
		}
		int[] vs = new int[N];
		for (int i = 0; i < N; i++) {
			vs[i] = -((c[i] << 10) | i); // use g[i].len than c[i]?
		}
		Arrays.sort(vs);
		for (int i = 0; i < N; i++) {
			vs[i] = (-vs[i]) & 0x3FF;
		}
		Solution sol = new Solution();
		int[] tis = new int[S];
		for (int i = 0; i < S; i++) {
			tis[i] = i;
		}
		IntAry after = new IntAry();
		for (int i = 0; i < S; i++) {
			int pos = rnd.nextInt(S - i) + i;
			swap(tis, i, pos);
			int[] mapping = findTree(tis[i], vs);
			if (mapping == null) {
				after.add(tis[i]);
			} else {
				sol.score += 100;
				addUsed(tis[i], mapping, sol);
			}
		}
		for (int i = 0; i < after.size; i++) {
			for (int j = 0; j < K; j++) {
				sol.v[after.a[i]][j] = j;
			}
		}
		sol.a = new IntAry();
		sol.b = new IntAry();
		for (int i = 0; i < N; i++) {
			for (int j = i + 1; j < N; j++) {
				if (used[i][j]) {
					sol.a.add(i);
					sol.b.add(j);
				}
			}
		}
//		sol.validate();
		return sol;
	}

	boolean[] usedInSearch = new boolean[N];

	int[] findTree(int ti, int[] vs) {
		for (int i = 0; i < 10; i++) {
			int[] ret = findTree(ti, vs[rnd.nextInt() & 127]);
			if (ret != null) {
				return ret;
			}
		}
		return null;
	}

	int[] findTree(int ti, int center) {
		int[] ret = new int[K];
		int[] tree = trees[ti];
		ret[0] = center;
		usedInSearch[center] = true;
		int depth = 1;
		int stopCount = 0;
		LOOP:
		for (int i = 0; i < 100000; i++) {
			if (depth == K) {
				Arrays.fill(usedInSearch, false);
				return ret;
			}
			if (stopCount == 100) {
				// backtrack
				if (depth == 1) break;
				for (int j = 1; j < depth; j++) {
					usedInSearch[ret[j]] = false;
				}
				depth = 1;
				continue;
			}
			int p = ret[tree[depth - 1]];
			int cur = g[p][rnd.nextInt(g[p].length)];
			if (usedInSearch[cur] || unusedCount[p][cur] > 0) {
				stopCount++;
				continue;
			}
			for (int j = 0; j < depth; j++) {
				if (j == tree[depth - 1]) continue;
				if (used[cur][ret[j]]) {
					stopCount++;
					continue LOOP;
				}
			}
			stopCount = 0;
			ret[depth] = cur;
			usedInSearch[cur] = true;
			depth++;
		}
		for (int j = 0; j < depth; j++) {
			usedInSearch[ret[j]] = false;
		}
		return null;
	}

	void addUsed(int ti, int[] mapping, Solution sol) {
		int[] tree = trees[ti];
		sol.v[ti][0] = mapping[0];
		for (int j = 1; j < K; j++) {
			sol.v[ti][j] = mapping[j];
			int t = mapping[j];
			int f = mapping[tree[j - 1]];
			assert (gEn[f][t]);
			used[f][t] = used[t][f] = true;
			usedCount[f][t]++;
			usedCount[t][f]++;
			for (int k = 0; k < j; k++) {
				if (k == tree[j - 1]) continue;
				int nf = mapping[k];
				assert (!used[t][nf]);
				unusedCount[nf][t]++;
				unusedCount[t][nf]++;
			}
		}
	}

	class Solution {
		IntAry a, b;
		int[][] v = new int[S][K];
		int score;

		void validate() {
			int score = 0;
			for (int i = 0; i < S; i++) {
				int otherEdge = 0;
				boolean ok = true;
				for (int j = 1; j < K; j++) {
					for (int k = 0; k < j; k++) {
						int t = v[i][j];
						int f = v[i][k];
						if (k == trees[i][j - 1]) {
							if (!used[f][t]) {
								ok = false;
							}
						} else {
							if (used[f][t]) {
								otherEdge++;
							}
						}
					}
				}
				if (!ok) {
					System.err.println("invalid");
				} else if (otherEdge == 0) {
					score += 100;
					System.err.println(100);
				} else if (otherEdge == 1) {
					score += 10;
					System.err.println(10);
				} else if (otherEdge == 2) {
					score += 1;
					System.err.println(1);
				} else {
					System.err.println(0);
				}
			}
			System.err.println("score:" + score);
		}
	}

	private static int sq(int v) {
		return v * v;
	}

	static final class IntAry {
		int[] a;
		int size;

		IntAry() {
			a = new int[16];
		}

		IntAry(int cap) {
			a = new int[cap];
		}

		IntAry(int[] a) {
			this.a = a;
			this.size = a.length;
		}

		IntAry(IntAry that) {
			a = that.a.clone();
			size = that.size;
		}

		@Override
		public String toString() {
			return Arrays.toString(Arrays.copyOf(a, size));
		}

		IntAry copyOf(int from, int to) {
			return new IntAry(Arrays.copyOfRange(this.a, from, to));
		}

		void add(int v) {
			if (size == a.length) {
				int[] na = new int[a.length * 2];
				System.arraycopy(a, 0, na, 0, size);
				a = na;
			}
			a[size++] = v;
		}

		void addAll(IntAry ia) {
			if (this.size + ia.size < a.length) {
				int[] na = new int[this.size + ia.size];
				System.arraycopy(a, 0, na, 0, size);
				a = na;
			}
			System.arraycopy(ia.a, 0, a, size, ia.size);
			size += ia.size;
		}

		void clear() {
			size = 0;
		}

		int pop() {
			size--;
			return a[size];
		}

		int back() {
			return a[size - 1];
		}

		void remove(int pos) {
			System.arraycopy(a, pos + 1, a, pos, size - pos - 1);
			size--;
		}

		void swapRemove(int pos) {
			swap(a, pos, size - 1);
			size--;
		}

		void sort() {
			Arrays.sort(a, 0, size);
		}
	}

	static void swap(int[] a, int p1, int p2) {
		int tmp = a[p1];
		a[p1] = a[p2];
		a[p2] = tmp;
	}

	static void debug(String fmt, Object... obj) {
		if (DEBUG) System.err.printf(fmt + "\n", obj);
	}
}

Submission Info

Submission Time
Task A - 千の木
User tomerun
Language Java8 (OpenJDK 1.8.0)
Score 5000000
Code Size 8116 Byte
Status AC
Exec Time 1085 ms
Memory 75780 KiB

Judge Result

Set Name Sample1 Sample2 Sample3 All
Score / Max Score 100000 / 100000 100000 / 100000 100000 / 100000 4700000 / 4700000
Status
AC × 1
AC × 1
AC × 1
AC × 47
Set Name Test Cases
Sample1 example_01.txt
Sample2 example_02.txt
Sample3 example_03.txt
All subtask_01_04.txt, subtask_01_05.txt, subtask_01_06.txt, subtask_01_07.txt, subtask_01_08.txt, subtask_01_09.txt, subtask_01_10.txt, subtask_01_11.txt, subtask_01_12.txt, subtask_01_13.txt, subtask_01_14.txt, subtask_01_15.txt, subtask_01_16.txt, subtask_01_17.txt, subtask_01_18.txt, subtask_01_19.txt, subtask_01_20.txt, subtask_01_21.txt, subtask_01_22.txt, subtask_01_23.txt, subtask_01_24.txt, subtask_01_25.txt, subtask_01_26.txt, subtask_01_27.txt, subtask_01_28.txt, subtask_01_29.txt, subtask_01_30.txt, subtask_01_31.txt, subtask_01_32.txt, subtask_01_33.txt, subtask_01_34.txt, subtask_01_35.txt, subtask_01_36.txt, subtask_01_37.txt, subtask_01_38.txt, subtask_01_39.txt, subtask_01_40.txt, subtask_01_41.txt, subtask_01_42.txt, subtask_01_43.txt, subtask_01_44.txt, subtask_01_45.txt, subtask_01_46.txt, subtask_01_47.txt, subtask_01_48.txt, subtask_01_49.txt, subtask_01_50.txt
Case Name Status Exec Time Memory
example_01.txt AC 1013 ms 71312 KiB
example_02.txt AC 1078 ms 68700 KiB
example_03.txt AC 1020 ms 67880 KiB
subtask_01_04.txt AC 1070 ms 72164 KiB
subtask_01_05.txt AC 1068 ms 71752 KiB
subtask_01_06.txt AC 1028 ms 68916 KiB
subtask_01_07.txt AC 1060 ms 67944 KiB
subtask_01_08.txt AC 1065 ms 70380 KiB
subtask_01_09.txt AC 1039 ms 71244 KiB
subtask_01_10.txt AC 1058 ms 66640 KiB
subtask_01_11.txt AC 1080 ms 66804 KiB
subtask_01_12.txt AC 1072 ms 71300 KiB
subtask_01_13.txt AC 1026 ms 71528 KiB
subtask_01_14.txt AC 1046 ms 65664 KiB
subtask_01_15.txt AC 1060 ms 66040 KiB
subtask_01_16.txt AC 1058 ms 58880 KiB
subtask_01_17.txt AC 1046 ms 60640 KiB
subtask_01_18.txt AC 1057 ms 68424 KiB
subtask_01_19.txt AC 1062 ms 67068 KiB
subtask_01_20.txt AC 1047 ms 68620 KiB
subtask_01_21.txt AC 1057 ms 69796 KiB
subtask_01_22.txt AC 1073 ms 69920 KiB
subtask_01_23.txt AC 1000 ms 71968 KiB
subtask_01_24.txt AC 1052 ms 70900 KiB
subtask_01_25.txt AC 1060 ms 70908 KiB
subtask_01_26.txt AC 1077 ms 73956 KiB
subtask_01_27.txt AC 1081 ms 67696 KiB
subtask_01_28.txt AC 1017 ms 67820 KiB
subtask_01_29.txt AC 1059 ms 66036 KiB
subtask_01_30.txt AC 1052 ms 71932 KiB
subtask_01_31.txt AC 1025 ms 71012 KiB
subtask_01_32.txt AC 1066 ms 70536 KiB
subtask_01_33.txt AC 1050 ms 68192 KiB
subtask_01_34.txt AC 1060 ms 62128 KiB
subtask_01_35.txt AC 1036 ms 70828 KiB
subtask_01_36.txt AC 1068 ms 70596 KiB
subtask_01_37.txt AC 1085 ms 69684 KiB
subtask_01_38.txt AC 1069 ms 70432 KiB
subtask_01_39.txt AC 1037 ms 71640 KiB
subtask_01_40.txt AC 1010 ms 62644 KiB
subtask_01_41.txt AC 1058 ms 72948 KiB
subtask_01_42.txt AC 1049 ms 75780 KiB
subtask_01_43.txt AC 1036 ms 71060 KiB
subtask_01_44.txt AC 1033 ms 62744 KiB
subtask_01_45.txt AC 1061 ms 68752 KiB
subtask_01_46.txt AC 1080 ms 71880 KiB
subtask_01_47.txt AC 1051 ms 69780 KiB
subtask_01_48.txt AC 1057 ms 71328 KiB
subtask_01_49.txt AC 1072 ms 69096 KiB
subtask_01_50.txt AC 1021 ms 63864 KiB